1 /* 2 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include <string.h> 25 #include "jvmti.h" 26 #include "agent_common.h" 27 #include "jni_tools.h" 28 #include "jvmti_tools.h" 29 30 extern "C" { 31 32 /* ============================================================================= */ 33 34 /* scaffold objects */ 35 static JNIEnv* jni = NULL; 36 static jvmtiEnv *jvmti = NULL; 37 static jlong timeout = 0; 38 39 /* constant names */ 40 #define DEBUGEE_CLASS_NAME "nsk/jvmti/scenarios/events/EM05/em05t001" 41 #define THREAD_CLASS_NAME "nsk/jvmti/scenarios/events/EM05/em05t001Thread" 42 #define THREAD_FIELD_NAME "thread" 43 #define THREAD_FIELD_SIG "L" THREAD_CLASS_NAME ";" 44 45 /* constants */ 46 #define MAX_NAME_LENGTH 64 47 #define EVENTS_COUNT 2 48 #define METHODS_COUNT 2 49 50 /* tested events */ 51 static jvmtiEvent eventsList[EVENTS_COUNT] = { 52 JVMTI_EVENT_COMPILED_METHOD_LOAD, 53 JVMTI_EVENT_COMPILED_METHOD_UNLOAD 54 }; 55 56 /* method description structure */ 57 typedef struct { 58 char methodName[MAX_NAME_LENGTH]; 59 char methodSig[MAX_NAME_LENGTH]; 60 jmethodID method; 61 int compiled; 62 int loadEvents; 63 int unloadEvents; 64 } MethodDesc; 65 66 /* descriptions of tested methods */ 67 static MethodDesc methodsDesc[METHODS_COUNT] = { 68 {"javaMethod", "(I)I", NULL, 0, 0, 0}, 69 {"nativeMethod", "(I)I", NULL, 0, 0, 0} 70 }; 71 72 /* ============================================================================= */ 73 74 /* testcase(s) */ 75 static int prepare(); 76 static int checkEvents(); 77 static int clean(); 78 79 /* ============================================================================= */ 80 81 /** Agent algorithm. */ 82 static void JNICALL 83 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 84 jni = agentJNI; 85 86 NSK_DISPLAY0("Wait for debuggee to become ready\n"); 87 if (!nsk_jvmti_waitForSync(timeout)) 88 return; 89 90 { 91 NSK_DISPLAY0("Prepare data\n"); 92 if (!prepare()) { 93 nsk_jvmti_setFailStatus(); 94 return; 95 } 96 97 NSK_DISPLAY0("Provoke methods compilation\n"); 98 if (!nsk_jvmti_resumeSync()) 99 return; 100 101 NSK_DISPLAY0("Wait for threads to complete\n"); 102 if (!nsk_jvmti_waitForSync(timeout)) 103 return; 104 105 NSK_DISPLAY0("Check if events received\n"); 106 if (!checkEvents()) 107 return; 108 109 NSK_DISPLAY0("Clean data\n"); 110 if (!clean()) { 111 nsk_jvmti_setFailStatus(); 112 return; 113 } 114 } 115 116 NSK_DISPLAY0("Let debuggee to finish\n"); 117 if (!nsk_jvmti_resumeSync()) 118 return; 119 } 120 121 /* ============================================================================= */ 122 123 /** 124 * Enable or disable tested events. 125 */ 126 static int enableEvents(jvmtiEventMode enable) { 127 int i; 128 129 for (i = 0; i < EVENTS_COUNT; i++) { 130 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(enable, eventsList[i], NULL))) { 131 nsk_jvmti_setFailStatus(); 132 return NSK_FALSE; 133 } 134 } 135 return NSK_TRUE; 136 } 137 138 /** 139 * Prepare data. 140 * - find tested thread 141 * - get tested methodIDs 142 * - enable events 143 */ 144 static int prepare() { 145 jclass debugeeClass = NULL; 146 jclass threadClass = NULL; 147 jfieldID threadFieldID = NULL; 148 jthread thread = NULL; 149 int i; 150 151 for (i = 0; i < METHODS_COUNT; i++) { 152 methodsDesc[i].method = (jmethodID)NULL; 153 methodsDesc[i].loadEvents = 0; 154 methodsDesc[i].unloadEvents = 0; 155 } 156 157 if (!NSK_JNI_VERIFY(jni, (debugeeClass = jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) 158 return NSK_FALSE; 159 160 if (!NSK_JNI_VERIFY(jni, (threadFieldID = 161 jni->GetStaticFieldID(debugeeClass, THREAD_FIELD_NAME, THREAD_FIELD_SIG)) != NULL)) 162 return NSK_FALSE; 163 164 if (!NSK_JNI_VERIFY(jni, (thread = (jthread) 165 jni->GetStaticObjectField(debugeeClass, threadFieldID)) != NULL)) 166 return NSK_FALSE; 167 168 if (!NSK_JNI_VERIFY(jni, (threadClass = jni->GetObjectClass(thread)) != NULL)) 169 return NSK_FALSE; 170 171 NSK_DISPLAY0("Find tested methods:\n"); 172 for (i = 0; i < METHODS_COUNT; i++) { 173 if (!NSK_JNI_VERIFY(jni, (methodsDesc[i].method = 174 jni->GetMethodID(threadClass, methodsDesc[i].methodName, methodsDesc[i].methodSig)) != NULL)) 175 return NSK_FALSE; 176 NSK_DISPLAY3(" method #%d (%s): 0x%p\n", 177 i, methodsDesc[i].methodName, (void*)methodsDesc[i].method); 178 } 179 180 NSK_DISPLAY0("Enable events\n"); 181 if (!nsk_jvmti_enableEvents(JVMTI_ENABLE, EVENTS_COUNT, eventsList, NULL)) 182 return NSK_FALSE; 183 184 return NSK_TRUE; 185 } 186 187 /** 188 * Testcase: check tested events. 189 * - check if expected events received for each method 190 * 191 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 192 */ 193 static int checkEvents() { 194 int i; 195 196 for (i = 0; i < METHODS_COUNT; i++) { 197 NSK_DISPLAY2(" method #%d (%s):\n", 198 i, methodsDesc[i].methodName); 199 NSK_DISPLAY2(" COMPILED_METHOD_LOAD: %d, COMPILED_METHOD_UNLOAD: %d\n", 200 methodsDesc[i].loadEvents, methodsDesc[i].unloadEvents); 201 202 if (methodsDesc[i].loadEvents <= 0) { 203 NSK_DISPLAY1("# WARNING: No COMPILED_METHOD_LOAD events for method: %s\n", 204 methodsDesc[i].methodName); 205 } 206 207 if (methodsDesc[i].unloadEvents > methodsDesc[i].loadEvents) { 208 NSK_DISPLAY1("# WARNING: Too many COMPILED_METHOD_UNLOAD events for method: %s\n", 209 methodsDesc[i].methodName); 210 NSK_DISPLAY2("# COMPILED_METHOD_LOAD: %d, COMPILED_METHOD_UNLOAD: %d\n", 211 methodsDesc[i].loadEvents, methodsDesc[i].unloadEvents); 212 } 213 } 214 return NSK_TRUE; 215 } 216 217 /** 218 * Clean data: 219 * - disable events 220 */ 221 static int clean() { 222 NSK_DISPLAY0("Disable events\n"); 223 if (!nsk_jvmti_enableEvents(JVMTI_DISABLE, EVENTS_COUNT, eventsList, NULL)) 224 return NSK_FALSE; 225 226 return NSK_TRUE; 227 } 228 229 /* ============================================================================= */ 230 231 /** 232 * COMPILED_METHOD_LOAD callback. 233 * - turn on flag if method is compiled 234 */ 235 JNIEXPORT void JNICALL 236 callbackCompiledMethodLoad(jvmtiEnv* jvmti, jmethodID method, 237 jint code_size, const void* code_addr, 238 jint map_length, const jvmtiAddrLocationMap* map, 239 const void* compile_info) { 240 int i; 241 242 for (i = 0; i < METHODS_COUNT; i++) { 243 if (methodsDesc[i].method == method) { 244 methodsDesc[i].loadEvents++; 245 NSK_DISPLAY3(" COMPILED_METHOD_LOAD for method #%d (%s): %d times\n", 246 i, methodsDesc[i].methodName, methodsDesc[i].loadEvents); 247 NSK_DISPLAY1(" methodID: 0x%p\n", 248 (void*)methodsDesc[i].method); 249 NSK_DISPLAY1(" code_size: %d\n", 250 (int)code_size); 251 NSK_DISPLAY1(" map_length: %d\n", 252 (int)map_length); 253 break; 254 } 255 } 256 } 257 258 /** 259 * COMPILED_METHOD_UNLOAD callback. 260 * - turn off flag that method is compiled 261 */ 262 JNIEXPORT void JNICALL 263 callbackCompiledMethodUnload(jvmtiEnv* jvmti, jmethodID method, 264 const void* code_addr) { 265 int i; 266 267 for (i = 0; i < METHODS_COUNT; i++) { 268 if (methodsDesc[i].method == method) { 269 methodsDesc[i].unloadEvents++; 270 NSK_DISPLAY3(" COMPILED_METHOD_UNLOAD for method #%d (%s): %d times\n", 271 i, methodsDesc[i].methodName, methodsDesc[i].loadEvents); 272 NSK_DISPLAY1(" methodID: 0x%p\n", 273 (void*)methodsDesc[i].method); 274 break; 275 } 276 } 277 } 278 279 /* ============================================================================= */ 280 281 /** Native running method in tested thread. */ 282 JNIEXPORT jint JNICALL 283 Java_nsk_jvmti_scenarios_events_EM05_em05t001Thread_nativeMethod(JNIEnv* jni, 284 jobject obj, 285 jint i) { 286 jint k = 0; 287 jint j; 288 289 for (j = 0; j < i; j++) { 290 k += (i - j); 291 } 292 return k; 293 } 294 295 /* ============================================================================= */ 296 297 /** Agent library initialization. */ 298 #ifdef STATIC_BUILD 299 JNIEXPORT jint JNICALL Agent_OnLoad_em05t001(JavaVM *jvm, char *options, void *reserved) { 300 return Agent_Initialize(jvm, options, reserved); 301 } 302 JNIEXPORT jint JNICALL Agent_OnAttach_em05t001(JavaVM *jvm, char *options, void *reserved) { 303 return Agent_Initialize(jvm, options, reserved); 304 } 305 JNIEXPORT jint JNI_OnLoad_em05t001(JavaVM *jvm, char *options, void *reserved) { 306 return JNI_VERSION_1_8; 307 } 308 #endif 309 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 310 311 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 312 return JNI_ERR; 313 314 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 315 316 if (!NSK_VERIFY((jvmti = 317 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 318 return JNI_ERR; 319 320 { 321 jvmtiCapabilities caps; 322 memset(&caps, 0, sizeof(caps)); 323 caps.can_generate_compiled_method_load_events = 1; 324 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 325 return JNI_ERR; 326 } 327 328 { 329 jvmtiEventCallbacks eventCallbacks; 330 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 331 eventCallbacks.CompiledMethodLoad = callbackCompiledMethodLoad; 332 eventCallbacks.CompiledMethodUnload = callbackCompiledMethodUnload; 333 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) 334 return JNI_ERR; 335 } 336 337 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 338 return JNI_ERR; 339 340 return JNI_OK; 341 } 342 343 /* ============================================================================= */ 344 345 }