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 JNIEnv* jni = NULL; 37 static jvmtiEnv *jvmti = NULL; 38 static jlong timeout = 0; 39 static jrawMonitorID syncLock = NULL; 40 41 /* constant names */ 42 #define JVMTI_EVENT_COUNT (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1) 43 #define EXPECTED_CLASS_NAME "Lnsk/jvmti/scenarios/events/EM01/em01t002a;" 44 #define CLASS_LOADER_COUNT_PARAM "classLoaderCount" 45 46 static int eventCount[JVMTI_EVENT_COUNT]; 47 48 static int classLoaderCount = 0; 49 50 static jvmtiPhase currentPhase; 51 52 /* ============================================================================= */ 53 /* ============================================================================= */ 54 55 56 /* 57 * Class: nsk_jvmti_scenarios_events_EM01_em01t002 58 * Method: loadClass 59 * Signature: (Lnsk/share/ClassLoader;Ljava/lang/String;)Ljava/lang/Class; 60 */ 61 JNIEXPORT jclass JNICALL 62 Java_nsk_jvmti_scenarios_events_EM01_em01t002_loadClass(JNIEnv *jni_env, 63 jobject o, jobject loader, jstring className) { 64 jclass klass; 65 jmethodID methodID; 66 jclass loadedClass; 67 68 klass = jni_env->GetObjectClass(loader); 69 if (!NSK_JNI_VERIFY(jni_env, klass != NULL)) { 70 nsk_jvmti_setFailStatus(); 71 return NULL; 72 } 73 74 methodID = jni_env->GetMethodID( 75 klass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); 76 if (!NSK_JNI_VERIFY(jni_env, methodID != NULL)) { 77 nsk_jvmti_setFailStatus(); 78 return NULL; 79 } 80 81 loadedClass = (jclass) jni_env->CallObjectMethod(loader, methodID, className); 82 if (!NSK_JNI_VERIFY(jni_env, loadedClass != NULL)) { 83 nsk_jvmti_setFailStatus(); 84 return NULL; 85 } 86 87 return loadedClass; 88 } 89 90 /* 91 * Class: nsk_jvmti_scenarios_events_EM01_em01t002 92 * Method: prepareClass 93 * Signature: (Ljava/lang/Class;)Z 94 */ 95 JNIEXPORT jboolean JNICALL 96 Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv *jni_env, 97 jobject o, jclass klass) { 98 jfieldID fieldID; 99 100 fieldID = jni_env->GetStaticFieldID(klass, "toProvokePreparation", "I"); 101 if (!NSK_JNI_VERIFY(jni_env, fieldID != NULL)) { 102 nsk_jvmti_setFailStatus(); 103 return NSK_FALSE; 104 } 105 106 return NSK_TRUE; 107 } 108 109 /* 110 * Class: nsk_jvmti_scenarios_events_EM01_em01t002 111 * Method: startThread 112 * Signature: (Ljava/lang/Thread;)Z 113 */ 114 JNIEXPORT jboolean JNICALL 115 Java_nsk_jvmti_scenarios_events_EM01_em01t002_startThread(JNIEnv *jni_env, 116 jobject o, jobject thread) { 117 jclass klass; 118 jmethodID methodID; 119 120 klass = jni_env->GetObjectClass(thread); 121 if (!NSK_JNI_VERIFY(jni_env, klass != NULL)) { 122 nsk_jvmti_setFailStatus(); 123 return NSK_FALSE; 124 } 125 126 methodID = jni_env->GetMethodID(klass, "start", "()V"); 127 if (!NSK_JNI_VERIFY(jni_env, methodID != NULL)) { 128 nsk_jvmti_setFailStatus(); 129 return NSK_FALSE; 130 } 131 132 if (!NSK_JNI_VERIFY_VOID(jni_env,jni_env->CallVoidMethod(thread, methodID)) ) { 133 nsk_jvmti_setFailStatus(); 134 return NSK_FALSE; 135 } 136 137 return NSK_TRUE; 138 } 139 140 /* ============================================================================= */ 141 /* ============================================================================= */ 142 143 static void 144 changeCount(jvmtiEvent event) { 145 146 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock))) 147 nsk_jvmti_setFailStatus(); 148 149 eventCount[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 static void 159 showEventStatistics() { 160 int i; 161 const char* str; 162 163 NSK_DISPLAY0("Event statistics\n"); 164 NSK_DISPLAY0("----------------\n"); 165 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 166 if (eventCount[i] > 0) { 167 str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL)); 168 NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]); 169 } 170 } 171 } 172 173 /* ========================================================================== */ 174 175 /* callbacks */ 176 void 177 classEventsHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env, 178 jclass klass) { 179 180 char *className; 181 char *generic; 182 jvmtiPhase phase; 183 184 if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, &generic))) { 185 nsk_jvmti_setFailStatus(); 186 return; 187 } 188 189 if (strcmp(className, EXPECTED_CLASS_NAME) == 0) { 190 changeCount(event); 191 NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n", 192 TranslateEvent(event), 193 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL], 194 className); 195 } 196 197 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) { 198 nsk_jvmti_setFailStatus(); 199 } 200 201 if (phase != currentPhase) { 202 NSK_DISPLAY2("Unexpected phase %s, but supposed %s", 203 TranslatePhase(phase), TranslatePhase(currentPhase)); 204 } 205 206 if ((phase != JVMTI_PHASE_LIVE) && (phase != JVMTI_PHASE_START)) { 207 NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n", 208 TranslateEvent(event), 209 TranslatePhase(phase), 210 phase, 211 className); 212 nsk_jvmti_setFailStatus(); 213 } 214 215 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) { 216 nsk_jvmti_setFailStatus(); 217 } 218 if (generic != NULL) 219 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) { 220 nsk_jvmti_setFailStatus(); 221 } 222 } 223 224 void 225 threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env, 226 jthread thread) { 227 jclass classObject; 228 char *className; 229 char *generic; 230 jvmtiPhase phase; 231 232 233 classObject = jni_env->GetObjectClass(thread); 234 if (!NSK_JNI_VERIFY(jni_env, classObject != NULL)) { 235 nsk_jvmti_setFailStatus(); 236 return; 237 } 238 239 if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classObject, &className, &generic))) { 240 nsk_jvmti_setFailStatus(); 241 return; 242 } 243 244 if (strcmp(className, EXPECTED_CLASS_NAME) == 0) { 245 changeCount(event); 246 NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n", 247 TranslateEvent(event), 248 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL], 249 className); 250 } 251 252 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) { 253 nsk_jvmti_setFailStatus(); 254 } 255 256 if (phase != currentPhase) { 257 NSK_DISPLAY2("Unexpected phase %s, but supposed %s", 258 TranslatePhase(phase), TranslatePhase(currentPhase)); 259 } 260 261 if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) { 262 NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n", 263 TranslateEvent(event), 264 TranslatePhase(phase), 265 phase, 266 className); 267 nsk_jvmti_setFailStatus(); 268 } 269 270 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) { 271 nsk_jvmti_setFailStatus(); 272 } 273 if (generic != NULL) 274 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) { 275 nsk_jvmti_setFailStatus(); 276 } 277 } 278 279 JNIEXPORT void JNICALL 280 cbVMStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env) { 281 282 jvmtiPhase phase; 283 284 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) { 285 nsk_jvmti_setFailStatus(); 286 } 287 288 if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) { 289 NSK_COMPLAIN3("%25s was sent during %s(%d)\n", 290 TranslateEvent(JVMTI_EVENT_VM_START), 291 TranslatePhase(phase), 292 phase); 293 nsk_jvmti_setFailStatus(); 294 } 295 296 changeCount(JVMTI_EVENT_VM_START); 297 currentPhase = JVMTI_PHASE_START; 298 } 299 300 JNIEXPORT void JNICALL 301 cbVMInit(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) { 302 303 jvmtiPhase phase; 304 305 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) { 306 nsk_jvmti_setFailStatus(); 307 } 308 309 if (phase != JVMTI_PHASE_LIVE) { 310 NSK_COMPLAIN3("%25s was sent during %s(%d)\n", 311 TranslateEvent(JVMTI_EVENT_VM_INIT), 312 TranslatePhase(phase), 313 phase); 314 nsk_jvmti_setFailStatus(); 315 } 316 317 changeCount(JVMTI_EVENT_VM_INIT); 318 currentPhase = JVMTI_PHASE_LIVE; 319 } 320 321 JNIEXPORT void JNICALL 322 cbVMDeath(jvmtiEnv* jvmti_env, JNIEnv* jni_env) { 323 324 jvmtiPhase phase; 325 326 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) { 327 nsk_jvmti_setFailStatus(); 328 } 329 330 if (phase != JVMTI_PHASE_LIVE) { 331 NSK_COMPLAIN3("%25s was sent during %s(%d)\n", 332 TranslateEvent(JVMTI_EVENT_VM_INIT), 333 TranslatePhase(phase), 334 phase); 335 nsk_jvmti_setFailStatus(); 336 } 337 338 currentPhase = JVMTI_PHASE_DEAD; 339 changeCount(JVMTI_EVENT_VM_DEATH); 340 341 if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock))) 342 nsk_jvmti_setFailStatus(); 343 344 } 345 346 JNIEXPORT void JNICALL 347 cbClassLoad(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, 348 jclass klass) { 349 350 classEventsHandler(JVMTI_EVENT_CLASS_LOAD, jvmti_env, jni_env, klass); 351 } 352 353 JNIEXPORT void JNICALL 354 cbClassPrepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, 355 jclass klass) { 356 357 classEventsHandler(JVMTI_EVENT_CLASS_PREPARE, jvmti_env, jni_env, klass); 358 } 359 360 JNIEXPORT void JNICALL 361 cbThreadStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) { 362 363 threadEventHandler(JVMTI_EVENT_THREAD_START, jvmti_env, jni_env, thread); 364 } 365 366 JNIEXPORT void JNICALL 367 cbThreadEnd(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) { 368 369 threadEventHandler(JVMTI_EVENT_THREAD_END, jvmti_env, jni_env, thread); 370 } 371 372 /* ============================================================================= */ 373 374 static int 375 enableEvent(jvmtiEventMode enable, jvmtiEvent event) { 376 377 if (enable == JVMTI_ENABLE) { 378 NSK_DISPLAY1("enabling %s\n", TranslateEvent(event)); 379 } else { 380 NSK_DISPLAY1("disabling %s\n", TranslateEvent(event)); 381 } 382 383 384 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(enable, event, NULL))) { 385 nsk_jvmti_setFailStatus(); 386 return NSK_FALSE; 387 } 388 389 return NSK_TRUE; 390 } 391 392 /* ============================================================================= */ 393 394 /** 395 * Testcase: check tested events. 396 * - check if expected events received for each method 397 * 398 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 399 */ 400 int checkEvents(int step) { 401 402 int i; 403 jvmtiEvent curr; 404 int result = NSK_TRUE; 405 int mustBeChecked; 406 407 showEventStatistics(); 408 409 for (i = 0; i < JVMTI_EVENT_COUNT; i++) { 410 411 curr = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL); 412 switch (step) { 413 case 1: 414 mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD) 415 || (curr == JVMTI_EVENT_CLASS_PREPARE)); 416 break; 417 418 case 2: 419 mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD) 420 || (curr == JVMTI_EVENT_CLASS_PREPARE) 421 || (curr == JVMTI_EVENT_THREAD_START) 422 || (curr == JVMTI_EVENT_THREAD_END)); 423 break; 424 default: 425 mustBeChecked = NSK_TRUE; 426 } 427 428 if (mustBeChecked && eventCount[i] != classLoaderCount) { 429 nsk_jvmti_setFailStatus(); 430 NSK_COMPLAIN3("Unexpected number of %s events %7d\n\texpected value %d\n", 431 TranslateEvent(curr), 432 eventCount[i], 433 classLoaderCount); 434 nsk_jvmti_setFailStatus(); 435 result = NSK_FALSE; 436 } 437 } 438 439 return result; 440 } 441 442 /* ============================================================================= */ 443 444 static int 445 setCallBacks() { 446 jvmtiEventCallbacks eventCallbacks; 447 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 448 449 eventCallbacks.VMStart = cbVMStart; 450 eventCallbacks.VMInit = cbVMInit; 451 eventCallbacks.VMDeath = cbVMDeath; 452 eventCallbacks.ClassLoad = cbClassLoad; 453 eventCallbacks.ClassPrepare = cbClassPrepare; 454 eventCallbacks.ThreadStart = cbThreadStart; 455 eventCallbacks.ThreadEnd = cbThreadEnd; 456 457 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)))) 458 return NSK_FALSE; 459 460 return NSK_TRUE; 461 } 462 463 /* ============================================================================= */ 464 465 /** Agent algorithm. */ 466 static void JNICALL 467 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 468 469 NSK_DISPLAY0("Wait for debuggee to become ready\n"); 470 if (!nsk_jvmti_waitForSync(timeout)) 471 return; 472 473 NSK_DISPLAY0("Let debuggee to load class\n"); 474 if (!nsk_jvmti_resumeSync()) 475 return; 476 477 if (!nsk_jvmti_waitForSync(timeout)) 478 return; 479 480 /* check only CLASS_LOAD and CLASS_PREPARE events */ 481 if (!checkEvents(1)) { 482 nsk_jvmti_setFailStatus(); 483 } 484 485 NSK_DISPLAY0("Let debuggee to start threads\n"); 486 if (!nsk_jvmti_resumeSync()) 487 return; 488 489 if (!nsk_jvmti_waitForSync(timeout)) 490 return; 491 492 NSK_DISPLAY0("check event 2\n"); 493 if (!checkEvents(2)) { 494 nsk_jvmti_setFailStatus(); 495 } 496 497 NSK_DISPLAY0("Let debuggee to finish\n"); 498 if (!nsk_jvmti_resumeSync()) 499 return; 500 501 } 502 503 /* ============================================================================= */ 504 505 /** Agent library initialization. */ 506 #ifdef STATIC_BUILD 507 JNIEXPORT jint JNICALL Agent_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) { 508 return Agent_Initialize(jvm, options, reserved); 509 } 510 JNIEXPORT jint JNICALL Agent_OnAttach_em01t002(JavaVM *jvm, char *options, void *reserved) { 511 return Agent_Initialize(jvm, options, reserved); 512 } 513 JNIEXPORT jint JNI_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) { 514 return JNI_VERSION_1_8; 515 } 516 #endif 517 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 518 519 currentPhase = JVMTI_PHASE_ONLOAD; 520 521 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 522 return JNI_ERR; 523 524 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 525 classLoaderCount = nsk_jvmti_findOptionIntValue(CLASS_LOADER_COUNT_PARAM, 10); 526 527 jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved); 528 if (!NSK_VERIFY(jvmti != NULL)) 529 return JNI_ERR; 530 531 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) { 532 nsk_jvmti_setFailStatus(); 533 return JNI_ERR; 534 } 535 536 if (!setCallBacks()) { 537 return JNI_ERR; 538 } 539 540 if (!enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD) 541 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE) 542 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START) 543 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END) 544 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_START) 545 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT) 546 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH) 547 ) { 548 NSK_COMPLAIN0("Events could not be enabled"); 549 nsk_jvmti_setFailStatus(); 550 return JNI_ERR; 551 } 552 553 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 554 return JNI_ERR; 555 556 currentPhase = JVMTI_PHASE_PRIMORDIAL; 557 558 return JNI_OK; 559 } 560 561 }