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