1 /* 2 * Copyright (c) 2004, 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 #include "JVMTITools.h" 30 31 extern "C" { 32 33 /* ============================================================================= */ 34 35 /* scaffold objects */ 36 static jvmtiEnv *jvmti = NULL; 37 static jlong timeout = 0; 38 static jrawMonitorID syncLock = NULL; 39 40 /* constant names */ 41 #define STEP_AMOUNT 3 42 #define JVMTI_EVENT_COUNT (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1) 43 44 static int eventCount[JVMTI_EVENT_COUNT]; 45 static int newEventCount[JVMTI_EVENT_COUNT]; 46 static int loadEvents = 0; 47 static int unloadEvents = 0; 48 49 /* ============================================================================= */ 50 51 static void 52 showEventStatistics(int step) { 53 int i; 54 const char* str; 55 int *currentCounts = (step == 1) ? &eventCount[0] : &newEventCount[0]; 56 57 NSK_DISPLAY0("\n"); 58 NSK_DISPLAY1("Event statistics for %d step:\n", step); 59 NSK_DISPLAY0("-----------------------------\n"); 60 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 61 if (currentCounts[i] > 0) { 62 str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL)); 63 NSK_DISPLAY2("%-40s %7d\n", str, currentCounts[i]); 64 } 65 } 66 } 67 68 /* ========================================================================== */ 69 70 int checkEvents(int step) { 71 int i; 72 jvmtiEvent curr; 73 int result = NSK_TRUE; 74 int *currentCounts; 75 int isExpected = 0; 76 77 switch (step) { 78 case 1: 79 currentCounts = &eventCount[0]; 80 break; 81 82 case 2: 83 case 3: 84 currentCounts = &newEventCount[0]; 85 break; 86 87 default: 88 NSK_COMPLAIN1("Unexpected step no: %d\n", step); 89 return NSK_FALSE; 90 } 91 92 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 93 94 curr = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL); 95 96 switch (step) { 97 case 1: 98 isExpected = ((curr == JVMTI_EVENT_COMPILED_METHOD_LOAD) 99 || (curr == JVMTI_EVENT_VM_INIT)); 100 break; 101 102 case 2: 103 isExpected = (curr == JVMTI_EVENT_COMPILED_METHOD_LOAD); 104 break; 105 106 case 3: 107 isExpected = (curr == JVMTI_EVENT_VM_DEATH); 108 break; 109 } 110 111 if (isExpected) { 112 if (currentCounts[i] < 0) { 113 NSK_COMPLAIN2("Unexpected events number %7d for %s\n\texpected value must be greater than 1\n", 114 currentCounts[i], 115 TranslateEvent(curr)); 116 result = NSK_FALSE; 117 } 118 } else { 119 120 if (curr != JVMTI_EVENT_COMPILED_METHOD_UNLOAD) { 121 if (currentCounts[i] > 0) { 122 NSK_COMPLAIN2("Unexpected event %s was sent %d times\n", 123 TranslateEvent(curr), 124 currentCounts[i]); 125 result = NSK_FALSE; 126 } 127 } 128 } 129 } 130 131 return result; 132 } 133 134 static void 135 changeCount(jvmtiEvent event, int *currentCounts) { 136 137 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock))) 138 nsk_jvmti_setFailStatus(); 139 140 currentCounts[event - JVMTI_MIN_EVENT_TYPE_VAL]++; 141 142 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(syncLock))) 143 nsk_jvmti_setFailStatus(); 144 145 } 146 147 /* ============================================================================= */ 148 149 /* callbacks */ 150 JNIEXPORT void JNICALL 151 cbVMInit(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread) { 152 changeCount(JVMTI_EVENT_VM_INIT, &eventCount[0]); 153 } 154 155 JNIEXPORT void JNICALL 156 cbVMDeath(jvmtiEnv* jvmti, JNIEnv* jni_env) { 157 changeCount(JVMTI_EVENT_VM_DEATH, &newEventCount[0]); 158 showEventStatistics(STEP_AMOUNT); 159 if (!checkEvents(STEP_AMOUNT)) 160 nsk_jvmti_setFailStatus(); 161 162 if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock))) 163 nsk_jvmti_setFailStatus(); 164 165 } 166 167 void JNICALL 168 cbException(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 169 jmethodID method, jlocation location, jobject exception, 170 jmethodID catch_method, jlocation catch_location) { 171 changeCount(JVMTI_EVENT_EXCEPTION, &eventCount[0]); 172 } 173 174 void JNICALL 175 cbExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 176 jmethodID method, jlocation location, jobject exception) { 177 changeCount(JVMTI_EVENT_EXCEPTION_CATCH, &eventCount[0]); 178 } 179 180 void JNICALL 181 cbSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 182 jmethodID method, jlocation location) { 183 changeCount(JVMTI_EVENT_SINGLE_STEP, &eventCount[0]); 184 } 185 186 void JNICALL 187 cbFramePop(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 188 jmethodID method, jboolean was_popped_by_exception) { 189 changeCount(JVMTI_EVENT_FRAME_POP, &eventCount[0]); 190 } 191 192 void JNICALL 193 cbBreakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 194 jmethodID method, jlocation location) { 195 changeCount(JVMTI_EVENT_BREAKPOINT, &eventCount[0]); 196 } 197 198 void JNICALL 199 cbFieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 200 jmethodID method, jlocation location, jclass field_klass, 201 jobject object, jfieldID field) { 202 changeCount(JVMTI_EVENT_FIELD_ACCESS, &eventCount[0]); 203 } 204 205 void JNICALL 206 cbFieldModification(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 207 jmethodID method, jlocation location, jclass field_klass, 208 jobject object, jfieldID field, char signature_type, 209 jvalue new_value) { 210 changeCount(JVMTI_EVENT_FIELD_MODIFICATION, &eventCount[0]); 211 } 212 213 void JNICALL 214 cbMethodEntry(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 215 jmethodID method) { 216 changeCount(JVMTI_EVENT_METHOD_ENTRY, &eventCount[0]); 217 } 218 219 void JNICALL 220 cbMethodExit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 221 jmethodID method, jboolean was_popped_by_exception, 222 jvalue return_value) { 223 changeCount(JVMTI_EVENT_METHOD_EXIT, &eventCount[0]); 224 } 225 226 void JNICALL 227 cbNativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv* jni_env,jthread thread, 228 jmethodID method, void* address, void** new_address_ptr) { 229 changeCount(JVMTI_EVENT_NATIVE_METHOD_BIND, &eventCount[0]); 230 } 231 232 void JNICALL 233 cbMonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 234 jobject object, jlong tout) { 235 236 changeCount(JVMTI_EVENT_MONITOR_WAIT, &eventCount[0]); 237 } 238 239 void JNICALL 240 cbMonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 241 jobject object, jboolean timed_out) { 242 243 changeCount(JVMTI_EVENT_MONITOR_WAITED, &eventCount[0]); 244 } 245 246 JNIEXPORT void JNICALL 247 cbMonitorContendedEnter(jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread, 248 jobject object) { 249 250 changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTER, &eventCount[0]); 251 } 252 253 void JNICALL 254 cbMonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 255 jobject object) { 256 257 changeCount(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, &eventCount[0]); 258 } 259 260 void 261 handlerMC1(jvmtiEvent event, jvmtiEnv* jvmti, jmethodID method) { 262 263 char *name; 264 char *sign; 265 char *genc; 266 267 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodName(method, &name, &sign, &genc))) { 268 nsk_jvmti_setFailStatus(); 269 return; 270 } 271 272 if (!strncmp(name,"javaMethod", 8)) { 273 NSK_DISPLAY2("\tMethod: %s, signature: %s\n", name, sign); 274 changeCount(event, &eventCount[0]); 275 } 276 277 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)name))) { 278 nsk_jvmti_setFailStatus(); 279 } 280 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)sign))) { 281 nsk_jvmti_setFailStatus(); 282 } 283 if (genc != NULL) 284 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)genc))) { 285 nsk_jvmti_setFailStatus(); 286 } 287 } 288 289 void JNICALL 290 cbCompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size, 291 const void* code_addr, jint map_length, 292 const jvmtiAddrLocationMap* map, const void* compile_info) { 293 294 loadEvents++; 295 handlerMC1(JVMTI_EVENT_COMPILED_METHOD_LOAD, jvmti_env, method); 296 } 297 298 void JNICALL 299 cbCompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method, 300 const void* code_addr) { 301 unloadEvents++; 302 NSK_DISPLAY0(">>>JVMTI_EVENT_COMPILED_METHOD_UNLOAD received for\n"); 303 changeCount(JVMTI_EVENT_COMPILED_METHOD_UNLOAD, &eventCount[0]); 304 } 305 306 void JNICALL 307 cbGarbageCollectionStart(jvmtiEnv *jvmti_env) { 308 changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_START, &eventCount[0]); 309 } 310 311 void JNICALL 312 cbGarbageCollectionFinish(jvmtiEnv *jvmti_env) { 313 changeCount(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, &eventCount[0]); 314 } 315 316 void JNICALL 317 cbObjectFree(jvmtiEnv *jvmti_env, jlong tag) { 318 changeCount(JVMTI_EVENT_OBJECT_FREE, &eventCount[0]); 319 } 320 321 void JNICALL 322 cbVMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, 323 jobject object, jclass object_klass, jlong size) { 324 325 changeCount(JVMTI_EVENT_VM_OBJECT_ALLOC, &eventCount[0]); 326 } 327 328 void 329 handlerMC2(jvmtiEvent event, jvmtiEnv* jvmti, jmethodID method) { 330 331 char *name; 332 char *sign; 333 char *genc; 334 335 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodName(method, &name, &sign, &genc))) { 336 nsk_jvmti_setFailStatus(); 337 return; 338 } 339 340 NSK_DISPLAY2("\tMethod: %s, signature: %s\n", name, sign); 341 changeCount(event, &newEventCount[0]); 342 343 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)name))) { 344 nsk_jvmti_setFailStatus(); 345 } 346 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)sign))) { 347 nsk_jvmti_setFailStatus(); 348 } 349 if (genc != NULL) 350 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)genc))) { 351 nsk_jvmti_setFailStatus(); 352 } 353 } 354 355 void JNICALL 356 cbNewCompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size, 357 const void* code_addr, jint map_length, 358 const jvmtiAddrLocationMap* map, const void* compile_info) { 359 360 loadEvents++; 361 handlerMC2(JVMTI_EVENT_COMPILED_METHOD_LOAD, jvmti_env, method); 362 } 363 364 void JNICALL 365 cbNewCompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method, 366 const void* code_addr) { 367 368 unloadEvents++; 369 NSK_DISPLAY0(">>>JVMTI_EVENT_COMPILED_METHOD_UNLOAD received for\n"); 370 changeCount(JVMTI_EVENT_COMPILED_METHOD_UNLOAD, &newEventCount[0]); 371 } 372 373 /* ============================================================================= */ 374 375 static int enableEvent(jvmtiEvent event) { 376 377 if (nsk_jvmti_isOptionalEvent(event) 378 && (event != JVMTI_EVENT_COMPILED_METHOD_LOAD) 379 && (event != JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) { 380 if (!NSK_JVMTI_VERIFY_CODE(JVMTI_ERROR_MUST_POSSESS_CAPABILITY, 381 jvmti->SetEventNotificationMode(JVMTI_ENABLE, event, NULL))) { 382 NSK_COMPLAIN1("Unexpected error enabling %s\n", 383 TranslateEvent(event)); 384 return NSK_FALSE; 385 } 386 } else { 387 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, event, NULL))) { 388 NSK_COMPLAIN1("Unexpected error enabling %s\n", 389 TranslateEvent(event)); 390 return NSK_FALSE; 391 } 392 } 393 394 return NSK_TRUE; 395 } 396 397 /** 398 * Enable or disable tested events. 399 */ 400 static int enableEventList() { 401 int i; 402 int result = NSK_TRUE; 403 404 NSK_DISPLAY0("Enable events\n"); 405 406 result = enableEvent(JVMTI_EVENT_VM_INIT); 407 408 result = result && enableEvent(JVMTI_EVENT_VM_DEATH); 409 410 /* enabling optional events */ 411 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 412 jvmtiEvent event = (jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL); 413 414 if (nsk_jvmti_isOptionalEvent(event)) 415 result = result && enableEvent(event); 416 } 417 418 if (result == NSK_FALSE) { 419 nsk_jvmti_setFailStatus(); 420 return NSK_FALSE; 421 } 422 423 return NSK_TRUE; 424 } 425 426 /* ============================================================================= */ 427 428 static int 429 setCallBacks(int step) { 430 431 int i; 432 433 jvmtiEventCallbacks eventCallbacks; 434 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 435 436 NSK_DISPLAY0("\n"); 437 NSK_DISPLAY1("===============step %d===============\n", step); 438 NSK_DISPLAY0("\n"); 439 switch (step) { 440 case 1: 441 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 442 eventCount[i] = 0; 443 } 444 445 eventCallbacks.VMInit = cbVMInit; 446 eventCallbacks.Exception = cbException; 447 eventCallbacks.ExceptionCatch = cbExceptionCatch; 448 eventCallbacks.SingleStep = cbSingleStep; 449 eventCallbacks.FramePop = cbFramePop; 450 eventCallbacks.Breakpoint = cbBreakpoint; 451 eventCallbacks.FieldAccess = cbFieldAccess; 452 eventCallbacks.FieldModification = cbFieldModification; 453 eventCallbacks.MethodEntry = cbMethodEntry; 454 eventCallbacks.MethodExit = cbMethodExit; 455 eventCallbacks.NativeMethodBind = cbNativeMethodBind; 456 eventCallbacks.CompiledMethodLoad = cbCompiledMethodLoad; 457 eventCallbacks.CompiledMethodUnload = cbCompiledMethodUnload; 458 eventCallbacks.MonitorWait = cbMonitorWait; 459 eventCallbacks.MonitorWaited = cbMonitorWaited; 460 eventCallbacks.MonitorContendedEnter = cbMonitorContendedEnter; 461 eventCallbacks.MonitorContendedEntered = cbMonitorContendedEntered; 462 eventCallbacks.GarbageCollectionStart = cbGarbageCollectionStart; 463 eventCallbacks.GarbageCollectionFinish = cbGarbageCollectionFinish; 464 eventCallbacks.ObjectFree = cbObjectFree; 465 eventCallbacks.VMObjectAlloc = cbVMObjectAlloc; 466 break; 467 468 case 2: 469 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 470 newEventCount[i] = 0; 471 } 472 473 eventCallbacks.CompiledMethodLoad = cbNewCompiledMethodLoad; 474 eventCallbacks.CompiledMethodUnload = cbNewCompiledMethodUnload; 475 break; 476 477 case 3: 478 479 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 480 newEventCount[i] = 0; 481 } 482 483 eventCallbacks.VMDeath = cbVMDeath; 484 break; 485 486 } 487 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) 488 return NSK_FALSE; 489 490 return NSK_TRUE; 491 } 492 493 /* ============================================================================= */ 494 495 /** Agent algorithm. */ 496 static void JNICALL 497 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 498 499 int i; 500 501 for (i = 1; i <= STEP_AMOUNT; i++) { 502 503 if (!nsk_jvmti_waitForSync(timeout)) 504 return; 505 506 NSK_DISPLAY0("Check received events\n"); 507 508 if (i < STEP_AMOUNT) { 509 showEventStatistics(i); 510 if (!checkEvents(i)) 511 nsk_jvmti_setFailStatus(); 512 513 if (!setCallBacks(i + 1)) { 514 return; 515 } 516 } 517 518 if (!nsk_jvmti_resumeSync()) 519 return; 520 } 521 522 /* checking amounts of COMPILED_METHOD_LOAD and COMPILED_METHOD_UNLOAD events */ 523 if (loadEvents < unloadEvents) { 524 NSK_COMPLAIN2("Number of JVMTI_EVENT_COMPILED_METHOD_LOAD events %d is less than number of JVMTI_EVENT_COMPILED_METHOD_UNLOAD %d", 525 loadEvents, 526 unloadEvents); 527 } 528 } 529 530 /* ============================================================================= */ 531 532 /** Agent library initialization. */ 533 #ifdef STATIC_BUILD 534 JNIEXPORT jint JNICALL Agent_OnLoad_em02t003(JavaVM *jvm, char *options, void *reserved) { 535 return Agent_Initialize(jvm, options, reserved); 536 } 537 JNIEXPORT jint JNICALL Agent_OnAttach_em02t003(JavaVM *jvm, char *options, void *reserved) { 538 return Agent_Initialize(jvm, options, reserved); 539 } 540 JNIEXPORT jint JNI_OnLoad_em02t003(JavaVM *jvm, char *options, void *reserved) { 541 return JNI_VERSION_1_8; 542 } 543 #endif 544 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 545 546 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 547 return JNI_ERR; 548 549 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 550 551 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 552 return JNI_ERR; 553 554 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) { 555 nsk_jvmti_setFailStatus(); 556 return JNI_ERR; 557 } 558 559 { 560 jvmtiCapabilities caps; 561 memset(&caps, 0, sizeof(caps)); 562 563 caps.can_generate_compiled_method_load_events = 1; 564 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 565 return JNI_ERR; 566 } 567 568 if (!setCallBacks(1)) { 569 return JNI_ERR; 570 } 571 572 nsk_jvmti_showPossessedCapabilities(jvmti); 573 574 if (!enableEventList()) { 575 return JNI_ERR; 576 } 577 578 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 579 return JNI_ERR; 580 581 return JNI_OK; 582 } 583 584 /* ============================================================================= */ 585 586 587 }