diff options
author | 2017-01-19 21:13:46 -0800 | |
---|---|---|
committer | 2017-01-20 15:33:25 -0800 | |
commit | 53ae7803b20650b7f36c0564dbcdc3115f399cba (patch) | |
tree | 6a163440ef06130506a0fcf21ac82d935a09dd1e | |
parent | d713d29507fb98bea3eee9277f05422a9b641ca1 (diff) |
ART: Refactor TI tests
Add a helper to explicitly bind native methods in a given class,
using dlsym to look up C functions in the local environment.
Add a callback helper that hooks VmInit and calls the above function
on the Main class. Use the callback helper before calling the test-
defined or shared minimal OnLoad function.
Add a binder helper that immediately binds the Main functions. Use
the helper before calling the test-defined OnAttach function.
Remove System.loadLibrary from tests. Instead rely on the explicit
binding.
In preparation for making the tests functional on device.
Test: m test-art-host
Change-Id: I12e68f070e8c6331e51d3a1fa4b9ebd8f28dfce6
36 files changed, 224 insertions, 60 deletions
diff --git a/test/901-hello-ti-agent/src/Main.java b/test/901-hello-ti-agent/src/Main.java index faf2dc2591..4d62ed3f5d 100644 --- a/test/901-hello-ti-agent/src/Main.java +++ b/test/901-hello-ti-agent/src/Main.java @@ -16,8 +16,6 @@ public class Main { public static void main(String[] args) { - System.loadLibrary(args[1]); - System.out.println("Hello, world!"); if (checkLivePhase()) { diff --git a/test/902-hello-transformation/src/Main.java b/test/902-hello-transformation/src/Main.java index ec4711954a..471c82ba28 100644 --- a/test/902-hello-transformation/src/Main.java +++ b/test/902-hello-transformation/src/Main.java @@ -49,7 +49,6 @@ public class Main { "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA="); public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform()); } diff --git a/test/903-hello-tagging/src/Main.java b/test/903-hello-tagging/src/Main.java index a8aedb410b..2f0365a921 100644 --- a/test/903-hello-tagging/src/Main.java +++ b/test/903-hello-tagging/src/Main.java @@ -20,7 +20,6 @@ import java.util.Arrays; public class Main { public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(); testGetTaggedObjects(); } diff --git a/test/904-object-allocation/src/Main.java b/test/904-object-allocation/src/Main.java index fc8a112e49..df59179cc8 100644 --- a/test/904-object-allocation/src/Main.java +++ b/test/904-object-allocation/src/Main.java @@ -18,8 +18,6 @@ import java.util.ArrayList; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - // Use a list to ensure objects must be allocated. ArrayList<Object> l = new ArrayList<>(100); diff --git a/test/905-object-free/src/Main.java b/test/905-object-free/src/Main.java index 16dec5d3e1..e41e378c19 100644 --- a/test/905-object-free/src/Main.java +++ b/test/905-object-free/src/Main.java @@ -19,8 +19,6 @@ import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/906-iterate-heap/src/Main.java b/test/906-iterate-heap/src/Main.java index 544a3656b2..cab27be4d2 100644 --- a/test/906-iterate-heap/src/Main.java +++ b/test/906-iterate-heap/src/Main.java @@ -19,8 +19,6 @@ import java.util.Collections; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/907-get-loaded-classes/src/Main.java b/test/907-get-loaded-classes/src/Main.java index 468d037a52..370185a4d9 100644 --- a/test/907-get-loaded-classes/src/Main.java +++ b/test/907-get-loaded-classes/src/Main.java @@ -20,8 +20,6 @@ import java.util.HashSet; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/908-gc-start-finish/src/Main.java b/test/908-gc-start-finish/src/Main.java index 2be0eea975..05388c917a 100644 --- a/test/908-gc-start-finish/src/Main.java +++ b/test/908-gc-start-finish/src/Main.java @@ -18,8 +18,6 @@ import java.util.ArrayList; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/910-methods/src/Main.java b/test/910-methods/src/Main.java index bf25a0d028..932a1ea414 100644 --- a/test/910-methods/src/Main.java +++ b/test/910-methods/src/Main.java @@ -20,8 +20,6 @@ import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt index dad08c9f97..2687f85b09 100644 --- a/test/911-get-stack-trace/expected.txt +++ b/test/911-get-stack-trace/expected.txt @@ -22,7 +22,7 @@ From top bar (IIILControlData;)J 0 24 foo (IIILControlData;)I 0 19 doTest ()V 38 23 - main ([Ljava/lang/String;)V 6 21 + main ([Ljava/lang/String;)V 3 21 --------- print (Ljava/lang/Thread;II)V 0 34 printOrWait (IILControlData;)V 6 39 @@ -42,7 +42,7 @@ From top bar (IIILControlData;)J 0 24 foo (IIILControlData;)I 0 19 doTest ()V 42 24 - main ([Ljava/lang/String;)V 6 21 + main ([Ljava/lang/String;)V 3 21 --------- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2 print (Ljava/lang/Thread;II)V 0 34 @@ -57,13 +57,13 @@ From top baz (IIILControlData;)Ljava/lang/Object; 9 32 From bottom --------- - main ([Ljava/lang/String;)V 6 21 + main ([Ljava/lang/String;)V 3 21 --------- baz (IIILControlData;)Ljava/lang/Object; 9 32 bar (IIILControlData;)J 0 24 foo (IIILControlData;)I 0 19 doTest ()V 65 30 - main ([Ljava/lang/String;)V 6 21 + main ([Ljava/lang/String;)V 3 21 --------- bar (IIILControlData;)J 0 24 foo (IIILControlData;)I 0 19 @@ -358,7 +358,7 @@ main getAllStackTraces (I)[[Ljava/lang/Object; -1 -2 printAll (I)V 0 73 doTest ()V 102 57 - main ([Ljava/lang/String;)V 30 33 + main ([Ljava/lang/String;)V 27 33 --------- FinalizerDaemon @@ -590,7 +590,7 @@ main getAllStackTraces (I)[[Ljava/lang/Object; -1 -2 printAll (I)V 0 73 doTest ()V 107 59 - main ([Ljava/lang/String;)V 30 33 + main ([Ljava/lang/String;)V 27 33 ######################################## @@ -659,7 +659,7 @@ main getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2 printList ([Ljava/lang/Thread;I)V 0 66 doTest ()V 96 52 - main ([Ljava/lang/String;)V 38 37 + main ([Ljava/lang/String;)V 35 37 --------- Thread-14 @@ -771,7 +771,7 @@ main getThreadListStackTraces ([Ljava/lang/Thread;I)[[Ljava/lang/Object; -1 -2 printList ([Ljava/lang/Thread;I)V 0 66 doTest ()V 101 54 - main ([Ljava/lang/String;)V 38 37 + main ([Ljava/lang/String;)V 35 37 ################### @@ -782,7 +782,7 @@ JVMTI_ERROR_ILLEGAL_ARGUMENT [public static native java.lang.Object[] Frames.getFrameLocation(java.lang.Thread,int), ffffffff] [public static void Frames.doTestSameThread(), 38] [public static void Frames.doTest() throws java.lang.Exception, 0] -[public static void Main.main(java.lang.String[]) throws java.lang.Exception, 2e] +[public static void Main.main(java.lang.String[]) throws java.lang.Exception, 2b] JVMTI_ERROR_NO_MORE_FRAMES ################################ diff --git a/test/911-get-stack-trace/src/Main.java b/test/911-get-stack-trace/src/Main.java index b199033c32..96a427d77b 100644 --- a/test/911-get-stack-trace/src/Main.java +++ b/test/911-get-stack-trace/src/Main.java @@ -16,7 +16,7 @@ public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); + bindTest911Classes(); SameThread.doTest(); @@ -42,4 +42,6 @@ public class Main { System.out.println("Done"); } + + private static native void bindTest911Classes(); } diff --git a/test/911-get-stack-trace/stack_trace.cc b/test/911-get-stack-trace/stack_trace.cc index d162e8a169..68f6d8dfb2 100644 --- a/test/911-get-stack-trace/stack_trace.cc +++ b/test/911-get-stack-trace/stack_trace.cc @@ -34,6 +34,14 @@ namespace Test911GetStackTrace { using android::base::StringPrintf; +extern "C" JNIEXPORT void JNICALL Java_Main_bindTest911Classes( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) { + BindFunctions(jvmti_env, env, "AllTraces"); + BindFunctions(jvmti_env, env, "Frames"); + BindFunctions(jvmti_env, env, "PrintThread"); + BindFunctions(jvmti_env, env, "ThreadListTraces"); +} + static jint FindLineNumber(jint line_number_count, jvmtiLineNumberEntry* line_number_table, jlocation location) { diff --git a/test/912-classes/src/Main.java b/test/912-classes/src/Main.java index cbf2392a73..8c78d71d4d 100644 --- a/test/912-classes/src/Main.java +++ b/test/912-classes/src/Main.java @@ -21,8 +21,6 @@ import java.util.Comparator; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/913-heaps/src/Main.java b/test/913-heaps/src/Main.java index 564596e02b..5a11a5b144 100644 --- a/test/913-heaps/src/Main.java +++ b/test/913-heaps/src/Main.java @@ -21,8 +21,6 @@ import java.util.HashSet; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); doFollowReferencesTest(); } diff --git a/test/914-hello-obsolescence/src/Main.java b/test/914-hello-obsolescence/src/Main.java index 46266efb28..8a1471693a 100644 --- a/test/914-hello-obsolescence/src/Main.java +++ b/test/914-hello-obsolescence/src/Main.java @@ -53,7 +53,6 @@ public class Main { "AAACIAAAEQAAAKIBAAADIAAAAgAAAJECAAAAIAAAAQAAAJ8CAAAAEAAAAQAAALACAAA="); public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform()); } diff --git a/test/915-obsolete-2/src/Main.java b/test/915-obsolete-2/src/Main.java index bbeb726858..0e3145c220 100644 --- a/test/915-obsolete-2/src/Main.java +++ b/test/915-obsolete-2/src/Main.java @@ -79,7 +79,6 @@ public class Main { "IAAAFwAAAD4CAAADIAAABAAAAAgEAAAAIAAAAQAAACYEAAAAEAAAAQAAADwEAAA="); public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform()); } diff --git a/test/916-obsolete-jit/src/Main.java b/test/916-obsolete-jit/src/Main.java index 1e43f7ee9d..1b03200ba5 100644 --- a/test/916-obsolete-jit/src/Main.java +++ b/test/916-obsolete-jit/src/Main.java @@ -113,7 +113,6 @@ public class Main { } public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform(), new TestWatcher()); } diff --git a/test/917-fields-transformation/src/Main.java b/test/917-fields-transformation/src/Main.java index 5378bb7a05..632a5c8b21 100644 --- a/test/917-fields-transformation/src/Main.java +++ b/test/917-fields-transformation/src/Main.java @@ -55,7 +55,6 @@ public class Main { "AAIgAAAMAAAAXAEAAAMgAAACAAAA4QEAAAAgAAABAAAA8AEAAAAQAAABAAAABAIAAA=="); public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform("Hello", "Goodbye"), new Transform("start", "end")); } diff --git a/test/918-fields/src/Main.java b/test/918-fields/src/Main.java index 8af6e7b375..3ba535b31b 100644 --- a/test/918-fields/src/Main.java +++ b/test/918-fields/src/Main.java @@ -19,8 +19,6 @@ import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/919-obsolete-fields/src/Main.java b/test/919-obsolete-fields/src/Main.java index 895c7a3fa4..1d893f125a 100644 --- a/test/919-obsolete-fields/src/Main.java +++ b/test/919-obsolete-fields/src/Main.java @@ -116,7 +116,6 @@ public class Main { } public static void main(String[] args) { - System.loadLibrary(args[1]); TestWatcher w = new TestWatcher(); doTest(new Transform(w), w); } diff --git a/test/921-hello-failure/src/Main.java b/test/921-hello-failure/src/Main.java index 43d6e9ed07..67ca1e15d6 100644 --- a/test/921-hello-failure/src/Main.java +++ b/test/921-hello-failure/src/Main.java @@ -18,7 +18,6 @@ import java.util.ArrayList; public class Main { public static void main(String[] args) { - System.loadLibrary(args[1]); NewName.doTest(new Transform()); DifferentAccess.doTest(new Transform()); NewInterface.doTest(new Transform2()); diff --git a/test/922-properties/src/Main.java b/test/922-properties/src/Main.java index 6cec6e97f2..8ad742f0ca 100644 --- a/test/922-properties/src/Main.java +++ b/test/922-properties/src/Main.java @@ -19,8 +19,6 @@ import java.util.TreeSet; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/923-monitors/src/Main.java b/test/923-monitors/src/Main.java index e35ce12608..ef00728d10 100644 --- a/test/923-monitors/src/Main.java +++ b/test/923-monitors/src/Main.java @@ -21,8 +21,6 @@ import java.util.List; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/924-threads/src/Main.java b/test/924-threads/src/Main.java index dec49a8320..58695f7e65 100644 --- a/test/924-threads/src/Main.java +++ b/test/924-threads/src/Main.java @@ -25,8 +25,6 @@ import java.util.Map; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/925-threadgroups/src/Main.java b/test/925-threadgroups/src/Main.java index c59efe2f7b..3d7a4ca740 100644 --- a/test/925-threadgroups/src/Main.java +++ b/test/925-threadgroups/src/Main.java @@ -19,8 +19,6 @@ import java.util.Comparator; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/926-multi-obsolescence/src/Main.java b/test/926-multi-obsolescence/src/Main.java index 8a6cf84b8b..6d9f96ca0e 100644 --- a/test/926-multi-obsolescence/src/Main.java +++ b/test/926-multi-obsolescence/src/Main.java @@ -92,7 +92,6 @@ public class Main { "AACUAQAAAiAAABEAAACiAQAAAyAAAAIAAACXAgAAACAAAAEAAAClAgAAABAAAAEAAAC0AgAA")); public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform(), new Transform2()); } diff --git a/test/927-timers/src/Main.java b/test/927-timers/src/Main.java index 2f5c85cab5..b67f66d3a7 100644 --- a/test/927-timers/src/Main.java +++ b/test/927-timers/src/Main.java @@ -18,8 +18,6 @@ import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/928-jni-table/src/Main.java b/test/928-jni-table/src/Main.java index b0baea1f9d..fd61b7d955 100644 --- a/test/928-jni-table/src/Main.java +++ b/test/928-jni-table/src/Main.java @@ -16,8 +16,6 @@ public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doJNITableTest(); System.out.println("Done"); diff --git a/test/929-search/src/Main.java b/test/929-search/src/Main.java index d253e6fdf6..bbeb0816c8 100644 --- a/test/929-search/src/Main.java +++ b/test/929-search/src/Main.java @@ -18,8 +18,6 @@ import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - doTest(); } diff --git a/test/930-hello-retransform/src/Main.java b/test/930-hello-retransform/src/Main.java index 12194c3235..0063c82897 100644 --- a/test/930-hello-retransform/src/Main.java +++ b/test/930-hello-retransform/src/Main.java @@ -49,7 +49,6 @@ public class Main { "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA="); public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform()); } diff --git a/test/931-agent-thread/src/Main.java b/test/931-agent-thread/src/Main.java index 6471bc8437..a7639fbfb2 100644 --- a/test/931-agent-thread/src/Main.java +++ b/test/931-agent-thread/src/Main.java @@ -18,8 +18,6 @@ import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { - System.loadLibrary(args[1]); - testAgentThread(); System.out.println("Done"); diff --git a/test/932-transform-saves/src/Main.java b/test/932-transform-saves/src/Main.java index d98ba6dbff..d960322071 100644 --- a/test/932-transform-saves/src/Main.java +++ b/test/932-transform-saves/src/Main.java @@ -79,7 +79,6 @@ public class Main { "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA="); public static void main(String[] args) { - System.loadLibrary(args[1]); doTest(new Transform()); } diff --git a/test/ti-agent/common_helper.cc b/test/ti-agent/common_helper.cc index 4bceef53bb..fd9fc38fb7 100644 --- a/test/ti-agent/common_helper.cc +++ b/test/ti-agent/common_helper.cc @@ -16,14 +16,18 @@ #include "ti-agent/common_helper.h" +#include <dlfcn.h> #include <stdio.h> #include <sstream> #include <deque> +#include "android-base/stringprintf.h" #include "art_method.h" #include "jni.h" +#include "jni_internal.h" #include "openjdkjvmti/jvmti.h" #include "scoped_thread_state_change-inl.h" +#include "ScopedLocalRef.h" #include "stack.h" #include "ti-agent/common_load.h" #include "utils.h" @@ -325,4 +329,123 @@ jint OnLoad(JavaVM* vm, } // namespace common_retransform +static void BindMethod(jvmtiEnv* jenv, + JNIEnv* env, + jclass klass, + jmethodID method) { + char* name; + char* signature; + jvmtiError name_result = jenv->GetMethodName(method, &name, &signature, nullptr); + if (name_result != JVMTI_ERROR_NONE) { + LOG(FATAL) << "Could not get methods"; + } + + ArtMethod* m = jni::DecodeArtMethod(method); + + std::string names[2]; + { + ScopedObjectAccess soa(Thread::Current()); + names[0] = m->JniShortName(); + names[1] = m->JniLongName(); + } + for (const std::string& mangled_name : names) { + void* sym = dlsym(nullptr, mangled_name.c_str()); + if (sym == nullptr) { + continue; + } + + JNINativeMethod native_method; + native_method.fnPtr = sym; + native_method.name = name; + native_method.signature = signature; + + env->RegisterNatives(klass, &native_method, 1); + + jenv->Deallocate(reinterpret_cast<unsigned char*>(name)); + jenv->Deallocate(reinterpret_cast<unsigned char*>(signature)); + return; + } + + LOG(FATAL) << "Could not find " << names[0]; +} + +static jclass FindClassWithSystemClassLoader(JNIEnv* env, const char* class_name) { + // Find the system classloader. + ScopedLocalRef<jclass> cl_klass(env, env->FindClass("java/lang/ClassLoader")); + if (cl_klass.get() == nullptr) { + return nullptr; + } + jmethodID getsystemclassloader_method = env->GetStaticMethodID(cl_klass.get(), + "getSystemClassLoader", + "()Ljava/lang/ClassLoader;"); + if (getsystemclassloader_method == nullptr) { + return nullptr; + } + ScopedLocalRef<jobject> cl(env, env->CallStaticObjectMethod(cl_klass.get(), + getsystemclassloader_method)); + if (cl.get() == nullptr) { + return nullptr; + } + + // Create a String of the name. + std::string descriptor = android::base::StringPrintf("L%s;", class_name); + std::string dot_name = DescriptorToDot(descriptor.c_str()); + ScopedLocalRef<jstring> name_str(env, env->NewStringUTF(dot_name.c_str())); + + // Call Class.forName with it. + ScopedLocalRef<jclass> c_klass(env, env->FindClass("java/lang/Class")); + if (c_klass.get() == nullptr) { + return nullptr; + } + jmethodID forname_method = env->GetStaticMethodID( + c_klass.get(), + "forName", + "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); + if (forname_method == nullptr) { + return nullptr; + } + + return reinterpret_cast<jclass>(env->CallStaticObjectMethod(c_klass.get(), + forname_method, + name_str.get(), + JNI_FALSE, + cl.get())); +} + +void BindFunctions(jvmtiEnv* jenv, JNIEnv* env, const char* class_name) { + // Use JNI to load the class. + ScopedLocalRef<jclass> klass(env, env->FindClass(class_name)); + if (klass.get() == nullptr) { + // We may be called with the wrong classloader. Try explicitly using the system classloader. + env->ExceptionClear(); + klass.reset(FindClassWithSystemClassLoader(env, class_name)); + if (klass.get() == nullptr) { + LOG(FATAL) << "Could not load " << class_name; + } + } + + // Use JVMTI to get the methods. + jint method_count; + jmethodID* methods; + jvmtiError methods_result = jenv->GetClassMethods(klass.get(), &method_count, &methods); + if (methods_result != JVMTI_ERROR_NONE) { + LOG(FATAL) << "Could not get methods"; + } + + // Check each method. + for (jint i = 0; i < method_count; ++i) { + jint modifiers; + jvmtiError mod_result = jenv->GetMethodModifiers(methods[i], &modifiers); + if (mod_result != JVMTI_ERROR_NONE) { + LOG(FATAL) << "Could not get methods"; + } + constexpr jint kNative = static_cast<jint>(kAccNative); + if ((modifiers & kNative) != 0) { + BindMethod(jenv, env, klass.get(), methods[i]); + } + } + + jenv->Deallocate(reinterpret_cast<unsigned char*>(methods)); +} + } // namespace art diff --git a/test/ti-agent/common_helper.h b/test/ti-agent/common_helper.h index 8599fc4d6c..c60553dc5a 100644 --- a/test/ti-agent/common_helper.h +++ b/test/ti-agent/common_helper.h @@ -71,6 +71,12 @@ void SetAllCapabilities(jvmtiEnv* env); bool JvmtiErrorToException(JNIEnv* env, jvmtiError error); +// Load the class through JNI. Inspect it, find all native methods. Construct the corresponding +// mangled name, run dlsym and bind the method. +// +// This will abort on failure. +void BindFunctions(jvmtiEnv* jvmti_env, JNIEnv* env, const char* class_name); + } // namespace art #endif // ART_TEST_TI_AGENT_COMMON_HELPER_H_ diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc index f4ce4c381e..8ed8e67e42 100644 --- a/test/ti-agent/common_load.cc +++ b/test/ti-agent/common_load.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "common_load.h" + #include <jni.h> #include <stdio.h> // TODO I don't know? @@ -22,7 +24,6 @@ #include "art_method-inl.h" #include "base/logging.h" #include "base/macros.h" -#include "common_load.h" #include "common_helper.h" #include "901-hello-ti-agent/basics.h" @@ -32,6 +33,8 @@ namespace art { jvmtiEnv* jvmti_env; +namespace { + using OnLoad = jint (*)(JavaVM* vm, char* options, void* reserved); using OnAttach = jint (*)(JavaVM* vm, char* options, void* reserved); @@ -41,11 +44,50 @@ struct AgentLib { OnAttach attach; }; +static void JNICALL VMInitCallback(jvmtiEnv *jvmti_env, + JNIEnv* jni_env, + jthread thread ATTRIBUTE_UNUSED) { + // Bind Main native methods. + BindFunctions(jvmti_env, jni_env, "Main"); +} + +// Install a phase callback that will bind JNI functions on VMInit. +bool InstallBindCallback(JavaVM* vm) { + // Use a new jvmtiEnv. Otherwise we might collide with table changes. + jvmtiEnv* install_env; + if (vm->GetEnv(reinterpret_cast<void**>(&install_env), JVMTI_VERSION_1_0) != 0) { + return false; + } + SetAllCapabilities(install_env); + + { + jvmtiEventCallbacks callbacks; + memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); + callbacks.VMInit = VMInitCallback; + + jvmtiError install_error = install_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); + if (install_error != JVMTI_ERROR_NONE) { + return false; + } + } + + { + jvmtiError enable_error = install_env->SetEventNotificationMode(JVMTI_ENABLE, + JVMTI_EVENT_VM_INIT, + nullptr); + if (enable_error != JVMTI_ERROR_NONE) { + return false; + } + } + + return true; +} + // A trivial OnLoad implementation that only initializes the global jvmti_env. static jint MinimalOnLoad(JavaVM* vm, char* options ATTRIBUTE_UNUSED, void* reserved ATTRIBUTE_UNUSED) { - if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) { + if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0) != 0) { printf("Unable to get jvmti env!\n"); return 1; } @@ -55,7 +97,7 @@ static jint MinimalOnLoad(JavaVM* vm, // A list of all non-standard the agents we have for testing. All other agents will use // MinimalOnLoad. -AgentLib agents[] = { +static AgentLib agents[] = { { "901-hello-ti-agent", Test901HelloTi::OnLoad, nullptr }, { "902-hello-transformation", common_redefine::OnLoad, nullptr }, { "909-attach-agent", nullptr, Test909AttachAgent::OnAttach }, @@ -101,6 +143,28 @@ static void SetIsJVM(char* options) { RuntimeIsJVM = strncmp(options, "jvm", 3) == 0; } +static bool BindFunctionsAttached(JavaVM* vm, const char* class_name) { + // Get a JNIEnv. As the thread is attached, we must not destroy it. + JNIEnv* env; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != 0) { + printf("Unable to get JNI env!\n"); + return false; + } + + jvmtiEnv* jenv; + if (vm->GetEnv(reinterpret_cast<void**>(&jenv), JVMTI_VERSION_1_0) != 0) { + printf("Unable to get jvmti env!\n"); + return false; + } + SetAllCapabilities(jenv); + + BindFunctions(jenv, env, class_name); + + return true; +} + +} // namespace + extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { char* remaining_options = nullptr; char* name_option = nullptr; @@ -111,6 +175,10 @@ extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* SetIsJVM(remaining_options); + if (!InstallBindCallback(vm)) { + return 1; + } + AgentLib* lib = FindAgent(name_option); OnLoad fn = nullptr; if (lib == nullptr) { @@ -132,6 +200,9 @@ extern "C" JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char* options, void printf("Unable to find agent name in options: %s\n", options); return -1; } + + BindFunctionsAttached(vm, "Main"); + AgentLib* lib = FindAgent(name_option); if (lib == nullptr) { printf("Unable to find agent named: %s, add it to the list in test/ti-agent/common_load.cc\n", diff --git a/test/ti-agent/common_load.h b/test/ti-agent/common_load.h index fac94b4c6e..d2544214ec 100644 --- a/test/ti-agent/common_load.h +++ b/test/ti-agent/common_load.h @@ -17,6 +17,7 @@ #ifndef ART_TEST_TI_AGENT_COMMON_LOAD_H_ #define ART_TEST_TI_AGENT_COMMON_LOAD_H_ +#include "jni.h" #include "openjdkjvmti/jvmti.h" namespace art { |