summaryrefslogtreecommitdiffstats
path: root/test/115-native-bridge
diff options
context:
space:
mode:
authorYong WU <yong.wu@intel.com>2014-08-03 16:06:52 +0800
committerYong WU <yong.wu@intel.com>2014-08-03 16:07:20 +0800
commitf7a68c1bd01db4e80003eb19cc8a4cdc8330adbe (patch)
tree106917930a223d84b8e25b28e8eb2d712afbaf60 /test/115-native-bridge
parent89c210bf418a152ccabfbbf853ddcce33aea450d (diff)
downloadart-f7a68c1bd01db4e80003eb19cc8a4cdc8330adbe.tar.gz
art-f7a68c1bd01db4e80003eb19cc8a4cdc8330adbe.tar.bz2
art-f7a68c1bd01db4e80003eb19cc8a4cdc8330adbe.zip
Add trampoline invoke and ART callback tests for native-bridge
Create trampolines for JNI functions in native-bridge. Test trampoline invoking from ART side. Add tests for ART callbacks which called from native-bridge. In this test they are invoked from the trampoline of JNI_OnLoad. Change-Id: Ibaa5103fdf49a6b29a1c12f45410fe5f82d46b1e
Diffstat (limited to 'test/115-native-bridge')
-rw-r--r--test/115-native-bridge/expected.txt62
-rw-r--r--test/115-native-bridge/nativebridge.cc199
2 files changed, 239 insertions, 22 deletions
diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt
index f852620b3a..5b41606b57 100644
--- a/test/115-native-bridge/expected.txt
+++ b/test/115-native-bridge/expected.txt
@@ -1,13 +1,55 @@
Ready for native bridge tests.
Native bridge initialized.
Checking for support.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
-Getting trampoline.
+Getting trampoline for JNI_OnLoad with shorty (null).
+Test ART callbacks: all JNI function number is 9.
+ name:booleanMethod, signature:(ZZZZZZZZZZ)Z, shorty:ZZZZZZZZZZZ.
+ name:byteMethod, signature:(BBBBBBBBBB)B, shorty:BBBBBBBBBBB.
+ name:charMethod, signature:(CCCCCCCCCC)C, shorty:CCCCCCCCCCC.
+ name:shortMethod, signature:(SSSSSSSSSS)S, shorty:SSSSSSSSSSS.
+ name:testCallStaticVoidMethodOnSubClassNative, signature:()V, shorty:V.
+ name:testFindClassOnAttachedNativeThread, signature:()V, shorty:V.
+ name:testFindFieldOnAttachedNativeThreadNative, signature:()V, shorty:V.
+ name:testGetMirandaMethodNative, signature:()Ljava/lang/reflect/Method;, shorty:L.
+ name:testZeroLengthByteBuffers, signature:()V, shorty:V.
+trampoline_JNI_OnLoad called!
+Getting trampoline for Java_Main_testFindClassOnAttachedNativeThread with shorty V.
+trampoline_Java_Main_testFindClassOnAttachedNativeThread called!
+Getting trampoline for Java_Main_testFindFieldOnAttachedNativeThreadNative with shorty V.
+trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative called!
+Getting trampoline for Java_Main_testCallStaticVoidMethodOnSubClassNative with shorty V.
+trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative called!
+Getting trampoline for Java_Main_testGetMirandaMethodNative with shorty L.
+trampoline_Java_Main_testGetMirandaMethodNative called!
+Getting trampoline for Java_Main_testZeroLengthByteBuffers with shorty V.
+trampoline_Java_Main_testZeroLengthByteBuffers called!
+Getting trampoline for Java_Main_byteMethod with shorty BBBBBBBBBBB.
+trampoline_Java_Main_byteMethod called!
+trampoline_Java_Main_byteMethod called!
+trampoline_Java_Main_byteMethod called!
+trampoline_Java_Main_byteMethod called!
+trampoline_Java_Main_byteMethod called!
+trampoline_Java_Main_byteMethod called!
+trampoline_Java_Main_byteMethod called!
+Getting trampoline for Java_Main_shortMethod with shorty SSSSSSSSSSS.
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+trampoline_Java_Main_shortMethod called!
+Getting trampoline for Java_Main_booleanMethod with shorty ZZZZZZZZZZZ.
+trampoline_Java_Main_booleanMethod called!
+trampoline_Java_Main_booleanMethod called!
+Getting trampoline for Java_Main_charMethod with shorty CCCCCCCCCCC.
+trampoline_Java_Main_charMethod called!
+trampoline_Java_Main_charMethod called!
+trampoline_Java_Main_charMethod called!
+trampoline_Java_Main_charMethod called!
+trampoline_Java_Main_charMethod called!
+trampoline_Java_Main_charMethod called!
+trampoline_Java_Main_charMethod called!
+trampoline_Java_Main_charMethod called!
diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc
index bd3ae13a30..82211a5579 100644
--- a/test/115-native-bridge/nativebridge.cc
+++ b/test/115-native-bridge/nativebridge.cc
@@ -44,13 +44,192 @@ struct NativeBridgeCallbacks {
bool (*isSupported)(const char* libpath);
};
+struct NativeBridgeMethod {
+ const char* name;
+ const char* signature;
+ bool static_method;
+ void* fnPtr;
+ void* trampoline;
+};
+
+static NativeBridgeMethod* find_native_bridge_method(const char *name);
+static NativeBridgeArtCallbacks* gNativeBridgeArtCallbacks;
+
+static jint trampoline_JNI_OnLoad(JavaVM* vm, void* reserved) {
+ JNIEnv* env = nullptr;
+ typedef jint (*FnPtr_t)(JavaVM*, void*);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("JNI_OnLoad")->fnPtr);
+
+ vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
+ if (env == nullptr) {
+ return 0;
+ }
+
+ jclass klass = env->FindClass("Main");
+ if (klass != nullptr) {
+ int i, count1, count2;
+ count1 = gNativeBridgeArtCallbacks->getNativeMethodCount(env, klass);
+ std::unique_ptr<JNINativeMethod[]> methods(new JNINativeMethod[count1]);
+ if (methods == nullptr) {
+ return 0;
+ }
+ count2 = gNativeBridgeArtCallbacks->getNativeMethods(env, klass, methods.get(), count1);
+ if (count1 == count2) {
+ printf("Test ART callbacks: all JNI function number is %d.\n", count1);
+ }
+
+ for (i = 0; i < count1; i++) {
+ NativeBridgeMethod* nb_method = find_native_bridge_method(methods[i].name);
+ if (nb_method != nullptr) {
+ jmethodID mid = nullptr;
+ if (nb_method->static_method) {
+ mid = env->GetStaticMethodID(klass, methods[i].name, nb_method->signature);
+ } else {
+ mid = env->GetMethodID(klass, methods[i].name, nb_method->signature);
+ }
+ if (mid != nullptr) {
+ const char* shorty = gNativeBridgeArtCallbacks->getMethodShorty(env, mid);
+ if (strcmp(shorty, methods[i].signature) == 0) {
+ printf(" name:%s, signature:%s, shorty:%s.\n",
+ methods[i].name, nb_method->signature, shorty);
+ }
+ }
+ }
+ }
+ methods.release();
+ }
+
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(vm, reserved);
+}
+
+static void trampoline_Java_Main_testFindClassOnAttachedNativeThread(JNIEnv* env,
+ jclass klass) {
+ typedef void (*FnPtr_t)(JNIEnv*, jclass);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>
+ (find_native_bridge_method("testFindClassOnAttachedNativeThread")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass);
+}
+
+static void trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv* env,
+ jclass klass) {
+ typedef void (*FnPtr_t)(JNIEnv*, jclass);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>
+ (find_native_bridge_method("testFindFieldOnAttachedNativeThreadNative")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass);
+}
+
+static void trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env,
+ jclass klass) {
+ typedef void (*FnPtr_t)(JNIEnv*, jclass);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>
+ (find_native_bridge_method("testCallStaticVoidMethodOnSubClassNative")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass);
+}
+
+static jobject trampoline_Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass klass) {
+ typedef jobject (*FnPtr_t)(JNIEnv*, jclass);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>
+ (find_native_bridge_method("testGetMirandaMethodNative")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass);
+}
+static void trampoline_Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass klass) {
+ typedef void (*FnPtr_t)(JNIEnv*, jclass);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>
+ (find_native_bridge_method("testZeroLengthByteBuffers")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass);
+}
+
+static jbyte trampoline_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) {
+ typedef jbyte (*FnPtr_t)(JNIEnv*, jclass, jbyte, jbyte, jbyte, jbyte, jbyte,
+ jbyte, jbyte, jbyte, jbyte, jbyte);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("byteMethod")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10);
+}
-static std::vector<void*> symbols;
+static jshort trampoline_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) {
+ typedef jshort (*FnPtr_t)(JNIEnv*, jclass, jshort, jshort, jshort, jshort, jshort,
+ jshort, jshort, jshort, jshort, jshort);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("shortMethod")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);
+}
+
+static jboolean trampoline_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) {
+ typedef jboolean (*FnPtr_t)(JNIEnv*, jclass, jboolean, jboolean, jboolean, jboolean, jboolean,
+ jboolean, jboolean, jboolean, jboolean, jboolean);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("booleanMethod")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10);
+}
+
+static jchar trampoline_Java_Main_charMethod(JNIEnv* env, jclass klass, jchar c1, jchar c2,
+ jchar c3, jchar c4, jchar c5, jchar c6,
+ jchar c7, jchar c8, jchar c9, jchar c10) {
+ typedef jchar (*FnPtr_t)(JNIEnv*, jclass, jchar, jchar, jchar, jchar, jchar,
+ jchar, jchar, jchar, jchar, jchar);
+ FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("charMethod")->fnPtr);
+ printf("%s called!\n", __FUNCTION__);
+ return fnPtr(env, klass, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10);
+}
+
+NativeBridgeMethod gNativeBridgeMethods[] = {
+ { "JNI_OnLoad", "", true, nullptr,
+ reinterpret_cast<void*>(trampoline_JNI_OnLoad) },
+ { "booleanMethod", "(ZZZZZZZZZZ)Z", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_booleanMethod) },
+ { "byteMethod", "(BBBBBBBBBB)B", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_byteMethod) },
+ { "charMethod", "(CCCCCCCCCC)C", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_charMethod) },
+ { "shortMethod", "(SSSSSSSSSS)S", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_shortMethod) },
+ { "testCallStaticVoidMethodOnSubClassNative", "()V", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative) },
+ { "testFindClassOnAttachedNativeThread", "()V", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_testFindClassOnAttachedNativeThread) },
+ { "testFindFieldOnAttachedNativeThreadNative", "()V", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative) },
+ { "testGetMirandaMethodNative", "()Ljava/lang/reflect/Method;", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_testGetMirandaMethodNative) },
+ { "testZeroLengthByteBuffers", "()V", true, nullptr,
+ reinterpret_cast<void*>(trampoline_Java_Main_testZeroLengthByteBuffers) },
+};
+
+static NativeBridgeMethod* find_native_bridge_method(const char *name) {
+ const char* pname = name;
+ if (strncmp(name, "Java_Main_", 10) == 0) {
+ pname += 10;
+ }
+
+ for (size_t i = 0; i < sizeof(gNativeBridgeMethods) / sizeof(gNativeBridgeMethods[0]); i++) {
+ if (strcmp(pname, gNativeBridgeMethods[i].name) == 0) {
+ return &gNativeBridgeMethods[i];
+ }
+ }
+ return nullptr;
+}
// NativeBridgeCallbacks implementations
extern "C" bool native_bridge_initialize(NativeBridgeArtCallbacks* art_cbs) {
- printf("Native bridge initialized.\n");
+ if (art_cbs != nullptr) {
+ gNativeBridgeArtCallbacks = art_cbs;
+ printf("Native bridge initialized.\n");
+ }
return true;
}
@@ -80,17 +259,16 @@ extern "C" void* native_bridge_loadLibrary(const char* libpath, int flag) {
extern "C" void* native_bridge_getTrampoline(void* handle, const char* name, const char* shorty,
uint32_t len) {
- printf("Getting trampoline.\n");
+ printf("Getting trampoline for %s with shorty %s.\n", name, shorty);
// The name here is actually the JNI name, so we can directly do the lookup.
void* sym = dlsym(handle, name);
- if (sym != nullptr) {
- symbols.push_back(sym);
- }
+ NativeBridgeMethod* method = find_native_bridge_method(name);
+ if (method == nullptr)
+ return nullptr;
+ method->fnPtr = sym;
- // As libarttest is the same arch as the host, we can actually directly use the code and do not
- // need to create a trampoline. :-)
- return sym;
+ return method->trampoline;
}
extern "C" bool native_bridge_isSupported(const char* libpath) {
@@ -109,6 +287,3 @@ NativeBridgeCallbacks NativeBridgeItf {
.getTrampoline = &native_bridge_getTrampoline,
.isSupported = &native_bridge_isSupported
};
-
-
-