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 {
ClassLoadSeenCallbackart::Test912ArtClasses::ClassLoadSeen78   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 
Java_art_Test912Art_enableClassLoadSeenEvents(JNIEnv * env,jclass Main_klass ATTRIBUTE_UNUSED,jboolean b)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 
Java_art_Test912Art_hadLoadEvent(JNIEnv * env ATTRIBUTE_UNUSED,jclass Main_klass ATTRIBUTE_UNUSED)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 
Java_art_Test912Art_isLoadedClass(JNIEnv * env,jclass Main_klass ATTRIBUTE_UNUSED,jstring class_name)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 
Java_art_Test912Art_ensureJitCompiled(JNIEnv * env,jclass klass,jclass test_class,jstring name)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 
Java_art_Test912Art_hasJit(JNIEnv * env,jclass klass)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