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