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