summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/jni/android_util_Binder.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 5b0f7768c165..883d4db04890 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -133,6 +133,14 @@ static struct strict_mode_callback_offsets_t
jmethodID mCallback;
} gStrictModeCallbackOffsets;
+static struct thread_dispatch_offsets_t
+{
+ // Class state.
+ jclass mClass;
+ jmethodID mDispatchUncaughtException;
+ jmethodID mCurrentThread;
+} gThreadDispatchOffsets;
+
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
@@ -166,6 +174,23 @@ static JNIEnv* javavm_to_jnienv(JavaVM* vm)
return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL;
}
+// Report a java.lang.Error (or subclass). This may terminate the runtime.
+static void report_java_lang_error(JNIEnv* env, jthrowable error)
+{
+ // Try to run the uncaught exception machinery.
+ jobject thread = env->CallStaticObjectMethod(gThreadDispatchOffsets.mClass,
+ gThreadDispatchOffsets.mCurrentThread);
+ if (thread != nullptr) {
+ env->CallVoidMethod(thread, gThreadDispatchOffsets.mDispatchUncaughtException,
+ error);
+ // Should not return here, unless more errors occured.
+ }
+ // Some error occurred that meant that either dispatchUncaughtException could not be
+ // called or that it had an error itself (as this should be unreachable under normal
+ // conditions). Clear the exception.
+ env->ExceptionClear();
+}
+
static void report_exception(JNIEnv* env, jthrowable excep, const char* msg)
{
env->ExceptionClear();
@@ -192,6 +217,10 @@ static void report_exception(JNIEnv* env, jthrowable excep, const char* msg)
}
if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
+ // Try to report the error. This should not return under normal circumstances.
+ report_java_lang_error(env, excep);
+ // The traditional handling: re-raise and abort.
+
/*
* It's an Error: Reraise the exception and ask the runtime to abort.
*/
@@ -1337,5 +1366,12 @@ int register_android_os_Binder(JNIEnv* env)
gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,
"onBinderStrictModePolicyChange", "(I)V");
+ clazz = FindClassOrDie(env, "java/lang/Thread");
+ gThreadDispatchOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
+ gThreadDispatchOffsets.mDispatchUncaughtException = GetMethodIDOrDie(env, clazz,
+ "dispatchUncaughtException", "(Ljava/lang/Throwable;)V");
+ gThreadDispatchOffsets.mCurrentThread = GetStaticMethodIDOrDie(env, clazz, "currentThread",
+ "()Ljava/lang/Thread;");
+
return 0;
}