diff options
| -rw-r--r-- | runtime/java_vm_ext.cc | 12 | ||||
| -rw-r--r-- | test/004-JniTest/jni_test.cc | 12 | ||||
| -rw-r--r-- | test/985-jni-onload-throw/expected.txt | 1 | ||||
| -rw-r--r-- | test/985-jni-onload-throw/info.txt | 1 | ||||
| -rw-r--r-- | test/985-jni-onload-throw/run | 3 | ||||
| -rw-r--r-- | test/985-jni-onload-throw/src/Main.java | 28 |
6 files changed, 57 insertions, 0 deletions
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index b93b8f2a97..f2e3353631 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -905,8 +905,20 @@ bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, EnsureFrontOfChain(SIGSEGV); } + // Temporarily reset any pending exception around the call to + // SetClassLoaderOverride: SetClassLoaderOverride creates a new + // global reference, which is illegal while we have an + // exception pending. + jthrowable on_load_exception = env->ExceptionOccurred(); + env->ExceptionClear(); + + // Restore the current class loader (which was overridden above) to the previous state. self->SetClassLoaderOverride(old_class_loader.get()); + if (on_load_exception != nullptr) { + env->Throw(on_load_exception); + } + if (version == JNI_ERR) { StringAppendF(error_msg, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str()); } else if (JavaVMExt::IsBadJniVersion(version)) { diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc index 81be531e44..20458e9548 100644 --- a/test/004-JniTest/jni_test.cc +++ b/test/004-JniTest/jni_test.cc @@ -41,6 +41,18 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void*) { jvm = vm; std::cout << "JNI_OnLoad called" << std::endl; + // Test 985 sets this environment variable in its run script to test + // for JNI_OnLoad failure. (We don't want to fail in the normal + // case, and a separate test library is overkill.) + if (getenv("ART_TEST_985_JNI_ONLOAD_THROW_THROW_IN_JNI_ONLOAD") != nullptr) { + JNIEnv* env; + jint res = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); + CHECK_EQ(res , JNI_OK); + res = env->ThrowNew(env->FindClass("java/lang/IllegalStateException"), + "message"); + CHECK_EQ(res, JNI_OK); + } + return JNI_VERSION_1_6; } diff --git a/test/985-jni-onload-throw/expected.txt b/test/985-jni-onload-throw/expected.txt new file mode 100644 index 0000000000..6a5618ebc6 --- /dev/null +++ b/test/985-jni-onload-throw/expected.txt @@ -0,0 +1 @@ +JNI_OnLoad called diff --git a/test/985-jni-onload-throw/info.txt b/test/985-jni-onload-throw/info.txt new file mode 100644 index 0000000000..d0174dde9b --- /dev/null +++ b/test/985-jni-onload-throw/info.txt @@ -0,0 +1 @@ +Test that returning from JNI_OnLoad with exception pending works. diff --git a/test/985-jni-onload-throw/run b/test/985-jni-onload-throw/run new file mode 100644 index 0000000000..ebd61f9b3f --- /dev/null +++ b/test/985-jni-onload-throw/run @@ -0,0 +1,3 @@ +# The environment variable set below makes JNI_OnLoad +# throw so that the test can try to catch the exception. +ART_TEST_985_JNI_ONLOAD_THROW_THROW_IN_JNI_ONLOAD=1 exec ${RUN} "${@}" diff --git a/test/985-jni-onload-throw/src/Main.java b/test/985-jni-onload-throw/src/Main.java new file mode 100644 index 0000000000..ade6dcd14b --- /dev/null +++ b/test/985-jni-onload-throw/src/Main.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class Main { + public static void main(String[] args) { + try { + System.loadLibrary(args[0]); + throw new AssertionError("loadLibrary did not throw"); + } catch (IllegalStateException ex) { + if (!"message".equals(ex.getMessage())) { + throw new AssertionError("exception thrown incorrectly"); + } + } + } +} |