You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stop leaving JNI exceptions pending across the native boundary
A Java method that throws does not unwind into C++. The exception is left
pending on the thread, and the runtime asserts on that at the next
transition: on a device, a throwing framework entry aborted system_server
with "No pending exception expected" and the phone boot looped. CheckJNI
is not needed for this; the assert is always on.
Six places let that happen. FindAndCall handed the framework entry to Java
and looked at nothing afterwards, so the abort was all anyone got, while
the log line above it still said the framework had been injected. Two
lookups in resources_hook returned JNI_FALSE to Java with
NoSuchMethodError pending, so a caller that asked for a boolean got a
throw. RegisterNatives, LogcatMonitor's refreshFd lookup and dex2oat's
string read did the same on their failure paths, and the obfuscation map
builder returned null on a failed FindClass without clearing, then fed two
unchecked method ids to NewObject.
Most of them are now the lsplant JNI wrappers, which clear the exception,
log the Java stack behind it, and return scoped references -- that last
part also releases the local reference the obfuscation map leaked per
entry. Where the caller has to know the outcome, the check stays explicit,
because a wrapper clears the exception before anyone can ask.
The trace is rendered through Log.getStackTraceString rather than
ExceptionDescribe. ExceptionDescribe writes to stderr, which in a process
forked from the zygote goes nowhere: measured on a device, it produced no
output at all, which would have traded an aborting-but-informative
tombstone for a survivable process and no stack.
SetAllowUnload(false) deliberately stays unconditional: the ART and JNI
hooks are installed before the entry runs and their trampolines point into
this library, so a failed entry is not a reason to let it be unloaded.
hook_bridge is untouched. It implements Method.invoke semantics and has to
leave a target's exception pending so it can wrap it in
InvocationTargetException.
0 commit comments