1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 19 #include <mutex> 20 #include <vector> 21 22 #include "android-base/macros.h" 23 #include "android-base/stringprintf.h" 24 25 #include "jni.h" 26 #include "jvmti.h" 27 28 // Test infrastructure 29 #include "jni_helper.h" 30 #include "jvmti_helper.h" 31 #include "scoped_local_ref.h" 32 #include "scoped_utf_chars.h" 33 #include "test_env.h" 34 35 namespace art { 36 namespace Test912ArtClasses { 37 38 static void EnableEvents(JNIEnv* env, 39 jboolean enable, 40 decltype(jvmtiEventCallbacks().ClassLoad) class_load, 41 decltype(jvmtiEventCallbacks().ClassPrepare) class_prepare) { 42 if (enable == JNI_FALSE) { 43 jvmtiError ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 44 JVMTI_EVENT_CLASS_LOAD, 45 nullptr); 46 if (JvmtiErrorToException(env, jvmti_env, ret)) { 47 return; 48 } 49 ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 50 JVMTI_EVENT_CLASS_PREPARE, 51 nullptr); 52 JvmtiErrorToException(env, jvmti_env, ret); 53 return; 54 } 55 56 jvmtiEventCallbacks callbacks; 57 memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); 58 callbacks.ClassLoad = class_load; 59 callbacks.ClassPrepare = class_prepare; 60 jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); 61 if (JvmtiErrorToException(env, jvmti_env, ret)) { 62 return; 63 } 64 65 ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 66 JVMTI_EVENT_CLASS_LOAD, 67 nullptr); 68 if (JvmtiErrorToException(env, jvmti_env, ret)) { 69 return; 70 } 71 ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 72 JVMTI_EVENT_CLASS_PREPARE, 73 nullptr); 74 JvmtiErrorToException(env, jvmti_env, ret); 75 } 76 77 struct ClassLoadSeen { 78 static void JNICALL ClassLoadSeenCallback(jvmtiEnv* jenv ATTRIBUTE_UNUSED, 79 JNIEnv* jni_env ATTRIBUTE_UNUSED, 80 jthread thread ATTRIBUTE_UNUSED, 81 jclass klass ATTRIBUTE_UNUSED) { 82 saw_event = true; 83 } 84 85 static bool saw_event; 86 }; 87 bool ClassLoadSeen::saw_event = false; 88 89 extern "C" JNIEXPORT void JNICALL Java_art_Test912Art_enableClassLoadSeenEvents( 90 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jboolean b) { 91 EnableEvents(env, b, ClassLoadSeen::ClassLoadSeenCallback, nullptr); 92 } 93 94 extern "C" JNIEXPORT jboolean JNICALL Java_art_Test912Art_hadLoadEvent( 95 JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass ATTRIBUTE_UNUSED) { 96 return ClassLoadSeen::saw_event ? JNI_TRUE : JNI_FALSE; 97 } 98 99 extern "C" JNIEXPORT jboolean JNICALL Java_art_Test912Art_isLoadedClass( 100 JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jstring class_name) { 101 ScopedUtfChars name(env, class_name); 102 103 jint class_count; 104 jclass* classes; 105 jvmtiError res = jvmti_env->GetLoadedClasses(&class_count, &classes); 106 if (JvmtiErrorToException(env, jvmti_env, res)) { 107 return JNI_FALSE; 108 } 109 110 bool found = false; 111 for (jint i = 0; !found && i < class_count; ++i) { 112 char* sig; 113 jvmtiError res2 = jvmti_env->GetClassSignature(classes[i], &sig, nullptr); 114 if (JvmtiErrorToException(env, jvmti_env, res2)) { 115 return JNI_FALSE; 116 } 117 118 found = strcmp(name.c_str(), sig) == 0; 119 120 CheckJvmtiError(jvmti_env, jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(sig))); 121 } 122 123 CheckJvmtiError(jvmti_env, jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(classes))); 124 125 return found; 126 } 127 128 // We use the implementations from runtime_state.cc. 129 130 extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env, 131 jclass, 132 jclass cls, 133 jstring method_name); 134 extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJit(JNIEnv*, jclass); 135 136 extern "C" JNIEXPORT void JNICALL Java_art_Test912Art_ensureJitCompiled( 137 JNIEnv* env, jclass klass, jclass test_class, jstring name) { 138 Java_Main_ensureJitCompiled(env, klass, test_class, name); 139 } 140 141 extern "C" JNIEXPORT jboolean JNICALL Java_art_Test912Art_hasJit(JNIEnv* env, jclass klass) { 142 return Java_Main_hasJit(env, klass); 143 } 144 145 } // namespace Test912ArtClasses 146 } // namespace art 147