summaryrefslogtreecommitdiffstats
path: root/test/004-JniTest
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2014-08-11 18:51:53 -0700
committerAndreas Gampe <agampe@google.com>2014-08-13 22:19:48 -0700
commit718ac65aa78403124c2269f0dcadd341a18b8efe (patch)
tree64bc497fb0366c7df8464c972601132e84579954 /test/004-JniTest
parente8bf3df2bcc61c12a7e66b4995a083f9ed3939e0 (diff)
downloadart-718ac65aa78403124c2269f0dcadd341a18b8efe.zip
art-718ac65aa78403124c2269f0dcadd341a18b8efe.tar.gz
art-718ac65aa78403124c2269f0dcadd341a18b8efe.tar.bz2
ART: Tolerate shallow call stack in VMStack_getCallingClassLoader
When the call stack does not have the three methods we expect, the visitor will return a nullptr value. Add a test to JniTest (and refactor the test a little for code reuse). Bug: 16867274 (cherry picked from commit 61bf6a1c80bf797af5d7911ff71fc367fdb36742) Change-Id: I5fb8f91f372a41e0bc11ef9f70640834591afa53
Diffstat (limited to 'test/004-JniTest')
-rw-r--r--test/004-JniTest/jni_test.cc195
-rw-r--r--test/004-JniTest/src/Main.java7
2 files changed, 117 insertions, 85 deletions
diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc
index 554712a..9a2fbdf 100644
--- a/test/004-JniTest/jni_test.cc
+++ b/test/004-JniTest/jni_test.cc
@@ -28,162 +28,133 @@
static JavaVM* jvm = NULL;
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) {
- assert(vm != NULL);
- assert(jvm == NULL);
+ assert(vm != nullptr);
+ assert(jvm == nullptr);
jvm = vm;
return JNI_VERSION_1_6;
}
-static void* testFindClassOnAttachedNativeThread(void*) {
- assert(jvm != NULL);
+static void* AttachHelper(void* arg) {
+ assert(jvm != nullptr);
- JNIEnv* env = NULL;
+ JNIEnv* env = nullptr;
JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, NULL };
int attach_result = jvm->AttachCurrentThread(&env, &args);
assert(attach_result == 0);
- jclass clazz = env->FindClass("Main");
- assert(clazz != NULL);
- assert(!env->ExceptionCheck());
-
- jobjectArray array = env->NewObjectArray(0, clazz, NULL);
- assert(array != NULL);
- assert(!env->ExceptionCheck());
+ typedef void (*Fn)(JNIEnv*);
+ Fn fn = reinterpret_cast<Fn>(arg);
+ fn(env);
int detach_result = jvm->DetachCurrentThread();
assert(detach_result == 0);
- return NULL;
+ return nullptr;
}
-// http://b/10994325
-extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*,
- jclass) {
+static void PthreadHelper(void (*fn)(JNIEnv*)) {
pthread_t pthread;
- int pthread_create_result = pthread_create(&pthread,
- NULL,
- testFindClassOnAttachedNativeThread,
- NULL);
+ int pthread_create_result = pthread_create(&pthread, nullptr, AttachHelper,
+ reinterpret_cast<void*>(fn));
assert(pthread_create_result == 0);
- int pthread_join_result = pthread_join(pthread, NULL);
+ int pthread_join_result = pthread_join(pthread, nullptr);
assert(pthread_join_result == 0);
}
-static void* testFindFieldOnAttachedNativeThread(void*) {
- assert(jvm != NULL);
+static void testFindClassOnAttachedNativeThread(JNIEnv* env) {
+ jclass clazz = env->FindClass("Main");
+ assert(clazz != nullptr);
+ assert(!env->ExceptionCheck());
- JNIEnv* env = NULL;
- JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, NULL };
- int attach_result = jvm->AttachCurrentThread(&env, &args);
- assert(attach_result == 0);
+ jobjectArray array = env->NewObjectArray(0, clazz, nullptr);
+ assert(array != nullptr);
+ assert(!env->ExceptionCheck());
+}
+// http://b/10994325
+extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(JNIEnv*, jclass) {
+ PthreadHelper(&testFindClassOnAttachedNativeThread);
+}
+
+static void testFindFieldOnAttachedNativeThread(JNIEnv* env) {
jclass clazz = env->FindClass("Main");
- assert(clazz != NULL);
+ assert(clazz != nullptr);
assert(!env->ExceptionCheck());
jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z");
- assert(field != NULL);
+ assert(field != nullptr);
assert(!env->ExceptionCheck());
env->SetStaticBooleanField(clazz, field, JNI_TRUE);
-
- int detach_result = jvm->DetachCurrentThread();
- assert(detach_result == 0);
- return NULL;
}
extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv*,
- jclass) {
- pthread_t pthread;
- int pthread_create_result = pthread_create(&pthread,
- NULL,
- testFindFieldOnAttachedNativeThread,
- NULL);
- assert(pthread_create_result == 0);
- int pthread_join_result = pthread_join(pthread, NULL);
- assert(pthread_join_result == 0);
+ jclass) {
+ PthreadHelper(&testFindFieldOnAttachedNativeThread);
}
-static void* testReflectFieldGetFromAttachedNativeThread(void*) {
- assert(jvm != NULL);
-
- JNIEnv* env = NULL;
- JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, NULL };
- int attach_result = jvm->AttachCurrentThread(&env, &args);
- assert(attach_result == 0);
-
+static void testReflectFieldGetFromAttachedNativeThread(JNIEnv* env) {
jclass clazz = env->FindClass("Main");
- assert(clazz != NULL);
+ assert(clazz != nullptr);
assert(!env->ExceptionCheck());
jclass class_clazz = env->FindClass("java/lang/Class");
- assert(class_clazz != NULL);
+ assert(class_clazz != nullptr);
assert(!env->ExceptionCheck());
jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField",
"(Ljava/lang/String;)Ljava/lang/reflect/Field;");
- assert(getFieldMetodId != NULL);
+ assert(getFieldMetodId != nullptr);
assert(!env->ExceptionCheck());
jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField");
- assert(field_name != NULL);
+ assert(field_name != nullptr);
assert(!env->ExceptionCheck());
jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name);
- assert(field != NULL);
+ assert(field != nullptr);
assert(!env->ExceptionCheck());
jclass field_clazz = env->FindClass("java/lang/reflect/Field");
- assert(field_clazz != NULL);
+ assert(field_clazz != nullptr);
assert(!env->ExceptionCheck());
jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean",
"(Ljava/lang/Object;)Z");
- assert(getBooleanMetodId != NULL);
+ assert(getBooleanMetodId != nullptr);
assert(!env->ExceptionCheck());
jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz);
assert(value == false);
assert(!env->ExceptionCheck());
-
- int detach_result = jvm->DetachCurrentThread();
- assert(detach_result == 0);
- return NULL;
}
// http://b/15539150
extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativeThreadNative(
JNIEnv*, jclass) {
- pthread_t pthread;
- int pthread_create_result = pthread_create(&pthread,
- NULL,
- testReflectFieldGetFromAttachedNativeThread,
- NULL);
- assert(pthread_create_result == 0);
- int pthread_join_result = pthread_join(pthread, NULL);
- assert(pthread_join_result == 0);
+ PthreadHelper(&testReflectFieldGetFromAttachedNativeThread);
}
// http://b/11243757
extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env,
- jclass) {
+ jclass) {
jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass");
- assert(super_class != NULL);
+ assert(super_class != nullptr);
jmethodID execute = env->GetStaticMethodID(super_class, "execute", "()V");
- assert(execute != NULL);
+ assert(execute != nullptr);
jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass");
- assert(sub_class != NULL);
+ assert(sub_class != nullptr);
env->CallStaticVoidMethod(sub_class, execute);
}
extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) {
jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract");
- assert(abstract_class != NULL);
+ assert(abstract_class != nullptr);
jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z");
- assert(miranda_method != NULL);
+ assert(miranda_method != nullptr);
return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE);
}
@@ -191,7 +162,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv
extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) {
std::vector<uint8_t> buffer(1);
jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0);
- assert(byte_buffer != NULL);
+ assert(byte_buffer != nullptr);
assert(!env->ExceptionCheck());
assert(env->GetDirectBufferAddress(byte_buffer) == &buffer[0]);
@@ -202,8 +173,8 @@ constexpr size_t kByteReturnSize = 7;
jbyte byte_returns[kByteReturnSize] = { 0, 1, 2, 127, -1, -2, -128 };
extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv* env, jclass klass, jbyte b1, jbyte b2,
- jbyte b3, jbyte b4, jbyte b5, jbyte b6,
- jbyte b7, jbyte b8, jbyte b9, jbyte b10) {
+ jbyte b3, jbyte b4, jbyte b5, jbyte b6,
+ jbyte b7, jbyte b8, jbyte b9, jbyte b10) {
// We use b1 to drive the output.
assert(b2 == 2);
assert(b3 == -3);
@@ -227,8 +198,8 @@ jshort short_returns[kShortReturnSize] = { 0, 1, 2, 127, 32767, -1, -2, -128,
// The weird static_cast is because short int is only guaranteed down to -32767, not Java's -32768.
extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv* env, jclass klass, jshort s1, jshort s2,
- jshort s3, jshort s4, jshort s5, jshort s6,
- jshort s7, jshort s8, jshort s9, jshort s10) {
+ jshort s3, jshort s4, jshort s5, jshort s6,
+ jshort s7, jshort s8, jshort s9, jshort s10) {
// We use s1 to drive the output.
assert(s2 == 2);
assert(s3 == -3);
@@ -247,9 +218,9 @@ extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv* env, jclass klass, jshor
}
extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv* env, jclass klass, jboolean b1,
- jboolean b2, jboolean b3, jboolean b4,
- jboolean b5, jboolean b6, jboolean b7,
- jboolean b8, jboolean b9, jboolean b10) {
+ jboolean b2, jboolean b3, jboolean b4,
+ jboolean b5, jboolean b6, jboolean b7,
+ jboolean b8, jboolean b9, jboolean b10) {
// We use b1 to drive the output.
assert(b2 == JNI_TRUE);
assert(b3 == JNI_FALSE);
@@ -269,8 +240,8 @@ constexpr size_t kCharReturnSize = 8;
jchar char_returns[kCharReturnSize] = { 0, 1, 2, 127, 255, 256, 15000, 34000 };
extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv* env, jclass klacc, jchar c1, jchar c2,
- jchar c3, jchar c4, jchar c5, jchar c6,
- jchar c7, jchar c8, jchar c9, jchar c10) {
+ jchar c3, jchar c4, jchar c5, jchar c6, jchar c7,
+ jchar c8, jchar c9, jchar c10) {
// We use c1 to drive the output.
assert(c2 == 'a');
assert(c3 == 'b');
@@ -291,3 +262,57 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_nativeIsAssignableFrom(JNIEnv* e
jclass from, jclass to) {
return env->IsAssignableFrom(from, to);
}
+
+static void testShallowGetCallingClassLoader(JNIEnv* env) {
+ // Test direct call.
+ {
+ jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
+ assert(vmstack_clazz != nullptr);
+ assert(!env->ExceptionCheck());
+
+ jmethodID getCallingClassLoaderMethodId = env->GetStaticMethodID(vmstack_clazz,
+ "getCallingClassLoader",
+ "()Ljava/lang/ClassLoader;");
+ assert(getCallingClassLoaderMethodId != nullptr);
+ assert(!env->ExceptionCheck());
+
+ jobject class_loader = env->CallStaticObjectMethod(vmstack_clazz,
+ getCallingClassLoaderMethodId);
+ assert(class_loader == nullptr);
+ assert(!env->ExceptionCheck());
+ }
+
+ // Test one-level call. Use System.loadLibrary().
+ {
+ jclass system_clazz = env->FindClass("java/lang/System");
+ assert(system_clazz != nullptr);
+ assert(!env->ExceptionCheck());
+
+ jmethodID loadLibraryMethodId = env->GetStaticMethodID(system_clazz, "loadLibrary",
+ "(Ljava/lang/String;)V");
+ assert(loadLibraryMethodId != nullptr);
+ assert(!env->ExceptionCheck());
+
+ // Create a string object.
+ jobject library_string = env->NewStringUTF("arttest");
+ assert(library_string != nullptr);
+ assert(!env->ExceptionCheck());
+
+ env->CallStaticVoidMethod(system_clazz, loadLibraryMethodId, library_string);
+ if (env->ExceptionCheck()) {
+ // At most we expect UnsatisfiedLinkError.
+ jthrowable thrown = env->ExceptionOccurred();
+ env->ExceptionClear();
+
+ jclass unsatisfied_link_error_clazz = env->FindClass("java/lang/UnsatisfiedLinkError");
+ jclass thrown_class = env->GetObjectClass(thrown);
+ assert(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class));
+ }
+ }
+}
+
+// http://b/16867274
+extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetCallingClassLoader(JNIEnv* env,
+ jclass) {
+ PthreadHelper(&testShallowGetCallingClassLoader);
+}
diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java
index ae133be..6d7d647 100644
--- a/test/004-JniTest/src/Main.java
+++ b/test/004-JniTest/src/Main.java
@@ -30,6 +30,7 @@ public class Main {
testBooleanMethod();
testCharMethod();
testIsAssignableFromOnPrimitiveTypes();
+ testShallowGetCallingClassLoader();
}
private static native void testFindClassOnAttachedNativeThread();
@@ -167,4 +168,10 @@ public class Main {
}
native static boolean nativeIsAssignableFrom(Class<?> from, Class<?> to);
+
+ static void testShallowGetCallingClassLoader() {
+ nativeTestShallowGetCallingClassLoader();
+ }
+
+ native static void nativeTestShallowGetCallingClassLoader();
}