diff options
| -rw-r--r-- | test/912-classes/classes.cc | 185 | ||||
| -rw-r--r-- | test/912-classes/src/Main.java | 55 | ||||
| -rw-r--r-- | test/Android.run-test.mk | 1 |
3 files changed, 70 insertions, 171 deletions
diff --git a/test/912-classes/classes.cc b/test/912-classes/classes.cc index e659ea3bfb..d13436ebf6 100644 --- a/test/912-classes/classes.cc +++ b/test/912-classes/classes.cc @@ -17,14 +17,9 @@ #include <stdio.h> #include "base/macros.h" -#include "class_linker.h" #include "jni.h" -#include "mirror/class_loader.h" #include "openjdkjvmti/jvmti.h" -#include "runtime.h" #include "ScopedLocalRef.h" -#include "ScopedUtfChars.h" -#include "scoped_thread_state_change-inl.h" #include "thread-inl.h" #include "ti-agent/common_helper.h" @@ -283,11 +278,69 @@ static std::string GetClassName(jvmtiEnv* jenv, JNIEnv* jni_env, jclass klass) { return tmp; } -static void EnableEvents(JNIEnv* env, - jboolean enable, - decltype(jvmtiEventCallbacks().ClassLoad) class_load, - decltype(jvmtiEventCallbacks().ClassPrepare) class_prepare) { - if (enable == JNI_FALSE) { +static std::string GetThreadName(jvmtiEnv* jenv, JNIEnv* jni_env, jthread thread) { + jvmtiThreadInfo info; + jvmtiError result = jenv->GetThreadInfo(thread, &info); + if (result != JVMTI_ERROR_NONE) { + if (jni_env != nullptr) { + JvmtiErrorToException(jni_env, result); + } else { + printf("Failed to get thread name.\n"); + } + return ""; + } + + std::string tmp(info.name); + jenv->Deallocate(reinterpret_cast<unsigned char*>(info.name)); + jni_env->DeleteLocalRef(info.context_class_loader); + jni_env->DeleteLocalRef(info.thread_group); + + return tmp; +} + +static std::string GetThreadName(Thread* thread) { + std::string tmp; + thread->GetThreadName(tmp); + return tmp; +} + +static void JNICALL ClassPrepareCallback(jvmtiEnv* jenv, + JNIEnv* jni_env, + jthread thread, + jclass klass) { + std::string name = GetClassName(jenv, jni_env, klass); + if (name == "") { + return; + } + std::string thread_name = GetThreadName(jenv, jni_env, thread); + if (thread_name == "") { + return; + } + std::string cur_thread_name = GetThreadName(Thread::Current()); + printf("Prepare: %s on %s (cur=%s)\n", + name.c_str(), + thread_name.c_str(), + cur_thread_name.c_str()); +} + +static void JNICALL ClassLoadCallback(jvmtiEnv* jenv, + JNIEnv* jni_env, + jthread thread, + jclass klass) { + std::string name = GetClassName(jenv, jni_env, klass); + if (name == "") { + return; + } + std::string thread_name = GetThreadName(jenv, jni_env, thread); + if (thread_name == "") { + return; + } + printf("Load: %s on %s\n", name.c_str(), thread_name.c_str()); +} + +extern "C" JNIEXPORT void JNICALL Java_Main_enableClassLoadEvents( + JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jboolean b) { + if (b == JNI_FALSE) { jvmtiError ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_CLASS_LOAD, nullptr); @@ -303,8 +356,8 @@ static void EnableEvents(JNIEnv* env, jvmtiEventCallbacks callbacks; memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); - callbacks.ClassLoad = class_load; - callbacks.ClassPrepare = class_prepare; + callbacks.ClassLoad = ClassLoadCallback; + callbacks.ClassPrepare = ClassPrepareCallback; jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); if (JvmtiErrorToException(env, ret)) { return; @@ -322,113 +375,5 @@ static void EnableEvents(JNIEnv* env, JvmtiErrorToException(env, ret); } -class ClassLoadPreparePrinter { - public: - static void JNICALL ClassLoadCallback(jvmtiEnv* jenv, - JNIEnv* jni_env, - jthread thread, - jclass klass) { - std::string name = GetClassName(jenv, jni_env, klass); - if (name == "") { - return; - } - std::string thread_name = GetThreadName(jenv, jni_env, thread); - if (thread_name == "") { - return; - } - printf("Load: %s on %s\n", name.c_str(), thread_name.c_str()); - } - - static void JNICALL ClassPrepareCallback(jvmtiEnv* jenv, - JNIEnv* jni_env, - jthread thread, - jclass klass) { - std::string name = GetClassName(jenv, jni_env, klass); - if (name == "") { - return; - } - std::string thread_name = GetThreadName(jenv, jni_env, thread); - if (thread_name == "") { - return; - } - std::string cur_thread_name = GetThreadName(Thread::Current()); - printf("Prepare: %s on %s (cur=%s)\n", - name.c_str(), - thread_name.c_str(), - cur_thread_name.c_str()); - } - - private: - static std::string GetThreadName(jvmtiEnv* jenv, JNIEnv* jni_env, jthread thread) { - jvmtiThreadInfo info; - jvmtiError result = jenv->GetThreadInfo(thread, &info); - if (result != JVMTI_ERROR_NONE) { - if (jni_env != nullptr) { - JvmtiErrorToException(jni_env, result); - } else { - printf("Failed to get thread name.\n"); - } - return ""; - } - - std::string tmp(info.name); - jenv->Deallocate(reinterpret_cast<unsigned char*>(info.name)); - jni_env->DeleteLocalRef(info.context_class_loader); - jni_env->DeleteLocalRef(info.thread_group); - - return tmp; - } - - static std::string GetThreadName(Thread* thread) { - std::string tmp; - thread->GetThreadName(tmp); - return tmp; - } -}; - -extern "C" JNIEXPORT void JNICALL Java_Main_enableClassLoadPreparePrintEvents( - JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jboolean enable) { - EnableEvents(env, - enable, - ClassLoadPreparePrinter::ClassLoadCallback, - ClassLoadPreparePrinter::ClassPrepareCallback); -} - -struct ClassLoadSeen { - static void JNICALL ClassLoadSeenCallback(jvmtiEnv* jenv ATTRIBUTE_UNUSED, - JNIEnv* jni_env ATTRIBUTE_UNUSED, - jthread thread ATTRIBUTE_UNUSED, - jclass klass ATTRIBUTE_UNUSED) { - saw_event = true; - } - - static bool saw_event; -}; -bool ClassLoadSeen::saw_event = false; - -extern "C" JNIEXPORT void JNICALL Java_Main_enableClassLoadSeenEvents( - JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jboolean b) { - EnableEvents(env, b, ClassLoadSeen::ClassLoadSeenCallback, nullptr); -} - -extern "C" JNIEXPORT jboolean JNICALL Java_Main_hadLoadEvent( - JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED) { - return ClassLoadSeen::saw_event ? JNI_TRUE : JNI_FALSE; -} - -extern "C" JNIEXPORT jboolean JNICALL Java_Main_isLoadedClass( - JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jstring class_name) { - ScopedUtfChars name(env, class_name); - ScopedObjectAccess soa(Thread::Current()); - Runtime* current = Runtime::Current(); - ClassLinker* class_linker = current->GetClassLinker(); - bool found = - class_linker->LookupClass( - soa.Self(), - name.c_str(), - soa.Decode<mirror::ClassLoader>(current->GetSystemClassLoader())) != nullptr; - return found ? JNI_TRUE : JNI_FALSE; -} - } // namespace Test912Classes } // namespace art diff --git a/test/912-classes/src/Main.java b/test/912-classes/src/Main.java index cec69194fe..6ad23a4869 100644 --- a/test/912-classes/src/Main.java +++ b/test/912-classes/src/Main.java @@ -219,14 +219,6 @@ public class Main { } final ClassLoader boot = cl; - // The JIT may deeply inline and load some classes. Preload these for test determinism. - final String PRELOAD_FOR_JIT[] = { - "java.nio.charset.CoderMalfunctionError" - }; - for (String s : PRELOAD_FOR_JIT) { - Class.forName(s); - } - Runnable r = new Runnable() { @Override public void run() { @@ -246,7 +238,7 @@ public class Main { ensureJitCompiled(Main.class, "testClassEvents"); - enableClassLoadPreparePrintEvents(true); + enableClassLoadEvents(true); ClassLoader cl1 = create(boot, DEX1, DEX2); System.out.println("B, false"); @@ -278,37 +270,7 @@ public class Main { t.start(); t.join(); - enableClassLoadPreparePrintEvents(false); - - // Note: the JIT part of this test is about the JIT pulling in a class not yet touched by - // anything else in the system. This could be the verifier or the interpreter. We - // block the interpreter by calling ensureJitCompiled. The verifier, however, must - // run in configurations where dex2oat didn't verify the class itself. So explicitly - // check whether the class has been already loaded, and skip then. - // TODO: Add multiple configurations to the run script once that becomes easier to do. - if (hasJit() && !isLoadedClass("Main$ClassD")) { - testClassEventsJit(); - } - } - - private static void testClassEventsJit() throws Exception { - enableClassLoadSeenEvents(true); - - testClassEventsJitImpl(); - - enableClassLoadSeenEvents(false); - - if (!hadLoadEvent()) { - throw new RuntimeException("Did not get expected load event."); - } - } - - private static void testClassEventsJitImpl() throws Exception { - ensureJitCompiled(Main.class, "testClassEventsJitImpl"); - - if (ClassD.x != 1) { - throw new RuntimeException("Unexpected value"); - } + enableClassLoadEvents(false); } private static void printClassLoaderClasses(ClassLoader cl) { @@ -373,14 +335,9 @@ public class Main { private static native int[] getClassVersion(Class<?> c); - private static native void enableClassLoadPreparePrintEvents(boolean b); - - private static native void ensureJitCompiled(Class<?> c, String name); + private static native void enableClassLoadEvents(boolean b); - private static native boolean hasJit(); - private static native boolean isLoadedClass(String name); - private static native void enableClassLoadSeenEvents(boolean b); - private static native boolean hadLoadEvent(); + private static native void ensureJitCompiled(Class c, String name); private static class TestForNonInit { public static double dummy = Math.random(); // So it can't be compile-time initialized. @@ -404,10 +361,6 @@ public class Main { public abstract static class ClassC implements InfA, InfC { } - public static class ClassD { - static int x = 1; - } - private static final String DEX1 = System.getenv("DEX_LOCATION") + "/912-classes.jar"; private static final String DEX2 = System.getenv("DEX_LOCATION") + "/912-classes-ex.jar"; diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 946d7e4b96..742353da46 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -547,6 +547,7 @@ TEST_ART_BROKEN_JIT_RUN_TESTS := \ 902-hello-transformation \ 904-object-allocation \ 906-iterate-heap \ + 912-classes \ 914-hello-obsolescence \ 915-obsolete-2 \ 917-fields-transformation \ |