summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andreas Gampe <agampe@google.com> 2017-01-19 21:13:46 -0800
committer Andreas Gampe <agampe@google.com> 2017-01-20 15:33:25 -0800
commit53ae7803b20650b7f36c0564dbcdc3115f399cba (patch)
tree6a163440ef06130506a0fcf21ac82d935a09dd1e
parentd713d29507fb98bea3eee9277f05422a9b641ca1 (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
-rw-r--r--test/901-hello-ti-agent/src/Main.java2
-rw-r--r--test/902-hello-transformation/src/Main.java1
-rw-r--r--test/903-hello-tagging/src/Main.java1
-rw-r--r--test/904-object-allocation/src/Main.java2
-rw-r--r--test/905-object-free/src/Main.java2
-rw-r--r--test/906-iterate-heap/src/Main.java2
-rw-r--r--test/907-get-loaded-classes/src/Main.java2
-rw-r--r--test/908-gc-start-finish/src/Main.java2
-rw-r--r--test/910-methods/src/Main.java2
-rw-r--r--test/911-get-stack-trace/expected.txt18
-rw-r--r--test/911-get-stack-trace/src/Main.java4
-rw-r--r--test/911-get-stack-trace/stack_trace.cc8
-rw-r--r--test/912-classes/src/Main.java2
-rw-r--r--test/913-heaps/src/Main.java2
-rw-r--r--test/914-hello-obsolescence/src/Main.java1
-rw-r--r--test/915-obsolete-2/src/Main.java1
-rw-r--r--test/916-obsolete-jit/src/Main.java1
-rw-r--r--test/917-fields-transformation/src/Main.java1
-rw-r--r--test/918-fields/src/Main.java2
-rw-r--r--test/919-obsolete-fields/src/Main.java1
-rw-r--r--test/921-hello-failure/src/Main.java1
-rw-r--r--test/922-properties/src/Main.java2
-rw-r--r--test/923-monitors/src/Main.java2
-rw-r--r--test/924-threads/src/Main.java2
-rw-r--r--test/925-threadgroups/src/Main.java2
-rw-r--r--test/926-multi-obsolescence/src/Main.java1
-rw-r--r--test/927-timers/src/Main.java2
-rw-r--r--test/928-jni-table/src/Main.java2
-rw-r--r--test/929-search/src/Main.java2
-rw-r--r--test/930-hello-retransform/src/Main.java1
-rw-r--r--test/931-agent-thread/src/Main.java2
-rw-r--r--test/932-transform-saves/src/Main.java1
-rw-r--r--test/ti-agent/common_helper.cc123
-rw-r--r--test/ti-agent/common_helper.h6
-rw-r--r--test/ti-agent/common_load.cc77
-rw-r--r--test/ti-agent/common_load.h1
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 {