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 <stdio.h> 25 #include <string.h> 26 #include <jvmti.h> 27 #include "agent_common.h" 28 29 #include "nsk_tools.h" 30 #include "jni_tools.h" 31 #include "JVMTITools.h" 32 #include "jvmti_tools.h" 33 34 extern "C" { 35 36 #define OBJ_MAX_COUNT 100000 37 38 static JNIEnv *jni = NULL; 39 static jvmtiEnv *jvmti = NULL; 40 static jvmtiEventCallbacks callbacks; 41 static jvmtiCapabilities caps; 42 43 static jlong timeout = 0; 44 45 static const char* DEBUGEE_SIGNATURE = "Lnsk/jvmti/scenarios/allocation/AP04/ap04t003;"; 46 static const char* ROOT_SIGNATURE = "[Lnsk/jvmti/scenarios/allocation/AP04/ap04t003;"; 47 48 static jclass debugeeClass = NULL; 49 static jfieldID rootFieldID; 50 51 static jrawMonitorID startLock = NULL; 52 static jrawMonitorID runLock = NULL; 53 static jrawMonitorID endLock = NULL; 54 55 static volatile int iterationCount = 0; 56 static volatile int objectCount = 0; 57 58 /***********************************************************************/ 59 60 static jrawMonitorID counterMonitor_ptr = NULL; 61 62 static void increaseCounter(volatile int* counterPtr) { 63 64 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(counterMonitor_ptr))) { 65 nsk_jvmti_setFailStatus(); 66 } 67 68 (*counterPtr)++; 69 70 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(counterMonitor_ptr))) { 71 nsk_jvmti_setFailStatus(); 72 } 73 } 74 75 static void setCounter(volatile int* counterPtr, int value) { 76 77 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(counterMonitor_ptr))) { 78 nsk_jvmti_setFailStatus(); 79 } 80 81 *counterPtr = value; 82 83 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(counterMonitor_ptr))) { 84 nsk_jvmti_setFailStatus(); 85 } 86 } 87 88 static int getCounter(volatile int* counterPtr) { 89 int result; 90 91 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(counterMonitor_ptr))) { 92 nsk_jvmti_setFailStatus(); 93 } 94 95 result = *counterPtr; 96 97 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(counterMonitor_ptr))) { 98 nsk_jvmti_setFailStatus(); 99 } 100 101 return result; 102 } 103 104 /***********************************************************************/ 105 106 void notifyThread() { 107 108 /* enter and notify runLock */ 109 { 110 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(runLock))) { 111 nsk_jvmti_setFailStatus(); 112 } 113 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorNotify(runLock))) { 114 nsk_jvmti_setFailStatus(); 115 } 116 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(runLock))) { 117 nsk_jvmti_setFailStatus(); 118 } 119 } 120 } 121 122 jvmtiIterationControl JNICALL 123 heapObjectCallback( jlong class_tag, 124 jlong size, 125 jlong* tag_ptr, 126 void* user_data) { 127 128 if (getCounter(&iterationCount) == 0) { 129 notifyThread(); 130 } 131 increaseCounter(&iterationCount); 132 133 if (*tag_ptr > 0) { 134 increaseCounter(&objectCount); 135 } 136 137 return JVMTI_ITERATION_CONTINUE; 138 } 139 140 /* jvmtiHeapRootCallback */ 141 jvmtiIterationControl JNICALL 142 heapRootCallback( jvmtiHeapRootKind root_kind, 143 jlong class_tag, 144 jlong size, 145 jlong* tag_ptr, 146 void* user_data) { 147 148 if (getCounter(&iterationCount) == 0) { 149 notifyThread(); 150 } 151 increaseCounter(&iterationCount); 152 153 if (*tag_ptr > 0) { 154 increaseCounter(&objectCount); 155 } 156 157 return JVMTI_ITERATION_CONTINUE; 158 } 159 160 /* jvmtiStackReferenceCallback */ 161 jvmtiIterationControl JNICALL 162 stackReferenceCallback( jvmtiHeapRootKind root_kind, 163 jlong class_tag, 164 jlong size, 165 jlong* tag_ptr, 166 jlong thread_tag, 167 jint depth, 168 jmethodID method, 169 jint slot, 170 void* user_data) { 171 172 if (getCounter(&iterationCount) == 0) { 173 notifyThread(); 174 } 175 increaseCounter(&iterationCount); 176 177 if (*tag_ptr > 0) { 178 increaseCounter(&objectCount); 179 } 180 181 return JVMTI_ITERATION_CONTINUE; 182 } 183 184 185 /* jvmtiObjectReferenceCallback */ 186 jvmtiIterationControl JNICALL 187 objectReferenceCallback( jvmtiObjectReferenceKind reference_kind, 188 jlong class_tag, 189 jlong size, 190 jlong* tag_ptr, 191 jlong referrer_tag, 192 jint referrer_index, 193 void* user_data) { 194 195 if (getCounter(&iterationCount) == 0) { 196 notifyThread(); 197 } 198 increaseCounter(&iterationCount); 199 200 if (*tag_ptr > 0) { 201 increaseCounter(&objectCount); 202 } 203 204 return JVMTI_ITERATION_CONTINUE; 205 } 206 207 /********* Agent thread modifying tags of objects ************/ 208 209 /** Body of new agent thread: modify tags of tagged object. */ 210 void JNICALL agent_start(jvmtiEnv* jvmti, JNIEnv* jni, void *p) { 211 212 jint taggedObjectsCount = 0; 213 jobject* taggedObjectsList = NULL; 214 215 NSK_DISPLAY0("Agent thread: started.\n"); 216 217 /* obtain tagged objects list */ 218 { 219 jlong tag = (jlong)1; 220 221 if (!NSK_JVMTI_VERIFY(jvmti->GetObjectsWithTags( 222 1, &tag, &taggedObjectsCount, &taggedObjectsList, NULL))) { 223 nsk_jvmti_setFailStatus(); 224 return; 225 } 226 } 227 228 NSK_DISPLAY1("Agent thread: got tagged objects: %d\n", (int)taggedObjectsCount); 229 230 if (!NSK_VERIFY(taggedObjectsCount == OBJ_MAX_COUNT)) { 231 nsk_jvmti_setFailStatus(); 232 return; 233 } 234 235 /* enter runLock */ 236 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(runLock))) { 237 nsk_jvmti_setFailStatus(); 238 } 239 240 /* enter and notify startLock */ 241 { 242 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(startLock))) { 243 nsk_jvmti_setFailStatus(); 244 } 245 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorNotify(startLock))) { 246 nsk_jvmti_setFailStatus(); 247 } 248 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(startLock))) { 249 nsk_jvmti_setFailStatus(); 250 } 251 } 252 253 NSK_DISPLAY0("Agent thread: wait for run notification\n"); 254 255 /* wait on runLock */ 256 { 257 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorWait(runLock, timeout))) { 258 nsk_jvmti_setFailStatus(); 259 } 260 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(runLock))) { 261 nsk_jvmti_setFailStatus(); 262 } 263 } 264 265 NSK_DISPLAY0("Agent thread: modify tags of each even object.\n"); 266 267 /* modify tags of each even object */ 268 { 269 int modified = 0; 270 int i; 271 for (i = 0; i < taggedObjectsCount; i+=2) { 272 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(taggedObjectsList[i], 0))) { 273 nsk_jvmti_setFailStatus(); 274 continue; 275 } 276 modified++; 277 } 278 279 NSK_DISPLAY2("Agent thread: tags modified: %d of %d\n", 280 modified, (int)taggedObjectsCount); 281 } 282 283 /* destroy objects list */ 284 { 285 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)taggedObjectsList))) { 286 nsk_jvmti_setFailStatus(); 287 } 288 } 289 290 /* enter and notify endLock */ 291 { 292 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(endLock))) { 293 nsk_jvmti_setFailStatus(); 294 } 295 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorNotify(endLock))) { 296 nsk_jvmti_setFailStatus(); 297 } 298 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(endLock))) { 299 nsk_jvmti_setFailStatus(); 300 } 301 } 302 303 NSK_DISPLAY0("Agent thread: finished.\n"); 304 } 305 306 /***********************************************************************/ 307 308 static int startThread(JNIEnv* jni, jthread threadObj) { 309 int success = NSK_TRUE; 310 311 /* enter startLock */ 312 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(startLock))) { 313 nsk_jvmti_setFailStatus(); 314 } 315 316 /* start thread */ 317 if (!NSK_JVMTI_VERIFY( 318 jvmti->RunAgentThread(threadObj, agent_start, NULL, JVMTI_THREAD_NORM_PRIORITY))) { 319 success = NSK_FALSE; 320 nsk_jvmti_setFailStatus(); 321 } else { 322 /* wait on startLock */ 323 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorWait(startLock, timeout))) { 324 nsk_jvmti_setFailStatus(); 325 } 326 } 327 328 /* exit starLock */ 329 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(startLock))) { 330 nsk_jvmti_setFailStatus(); 331 } 332 333 return success; 334 } 335 336 /** Create thread object for new agent thread. */ 337 static jthread newThreadObj(JNIEnv* jni) { 338 jclass thrClass; 339 jmethodID cid; 340 jthread result = NULL; 341 342 if (!NSK_JNI_VERIFY(jni, (thrClass = jni->FindClass("java/lang/Thread")) != NULL )) { 343 nsk_jvmti_setFailStatus(); 344 return result; 345 } 346 347 if (!NSK_JNI_VERIFY(jni, (cid = jni->GetMethodID(thrClass, "<init>", "()V")) != NULL )) { 348 nsk_jvmti_setFailStatus(); 349 return result; 350 } 351 352 if (!NSK_JNI_VERIFY(jni, (result = jni->NewObject(thrClass, cid)) != NULL )) { 353 nsk_jvmti_setFailStatus(); 354 return result; 355 } 356 357 return result; 358 } 359 360 /***********************************************************************/ 361 362 /** Clean counters and start new agent thread with agent_start() body. */ 363 static int prepareToIteration (JNIEnv* jni) { 364 jthread threadObj = NULL; 365 366 setCounter(&iterationCount, 0); 367 setCounter(&objectCount, 0); 368 369 if (!NSK_VERIFY((threadObj = newThreadObj(jni)) != NULL)) { 370 nsk_jvmti_setFailStatus(); 371 return NSK_FALSE; 372 } 373 374 /* enter endLock */ 375 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(endLock))) { 376 nsk_jvmti_setFailStatus(); 377 } 378 379 NSK_DISPLAY0("Starting new agent thread...\n"); 380 return startThread(jni, threadObj); 381 } 382 383 /** Wait for new agent thread to complete. */ 384 static void afterIteration (JNIEnv* jni) { 385 386 /* notify new agent thread (in case if not yet notified) */ 387 notifyThread(); 388 389 NSK_DISPLAY0("Wait for new agent thread to complete\n"); 390 391 /* wait on endLock */ 392 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorWait(endLock, timeout))) { 393 nsk_jvmti_setFailStatus(); 394 } 395 396 /* exit endLock */ 397 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(endLock))) { 398 nsk_jvmti_setFailStatus(); 399 } 400 } 401 402 /***********************************************************************/ 403 404 JNIEXPORT void JNICALL 405 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_setTag( JNIEnv* jni, 406 jclass klass, 407 jobject target, /* object to be tagged */ 408 jlong tag ) { 409 410 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(target, tag))) { 411 nsk_jvmti_setFailStatus(); 412 } 413 } 414 415 JNIEXPORT void JNICALL 416 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverHeap( JNIEnv* jni, 417 jclass klass ) { 418 int modified = 0; 419 int found = 0; 420 421 if (!prepareToIteration(jni)) 422 return; 423 424 NSK_DISPLAY0("Calling IterateOverHeap...\n"); 425 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_TAGGED, 426 heapObjectCallback, 427 NULL /*user_data*/))) { 428 nsk_jvmti_setFailStatus(); 429 } 430 NSK_DISPLAY0("IterateOverHeap finished.\n"); 431 432 afterIteration(jni); 433 434 found = getCounter(&objectCount); 435 NSK_DISPLAY1("Found tagged objects: %d\n", found); 436 437 modified = OBJ_MAX_COUNT - found; 438 if (modified > 0) { 439 NSK_COMPLAIN2("Tags were modified by other thread during heap iteration: %d of %d\n", 440 modified, OBJ_MAX_COUNT); 441 nsk_jvmti_setFailStatus(); 442 } 443 } 444 445 JNIEXPORT void JNICALL 446 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverReachableObjects( JNIEnv* jni, 447 jclass klass ) { 448 int modified = 0; 449 int found = 0; 450 451 if (!prepareToIteration(jni)) 452 return; 453 454 NSK_DISPLAY0("Calling IterateOverReachableObjects...\n"); 455 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverReachableObjects(heapRootCallback, 456 stackReferenceCallback, 457 objectReferenceCallback, 458 NULL /*user_data*/))) { 459 nsk_jvmti_setFailStatus(); 460 } 461 NSK_DISPLAY0("IterateOverReachableObjects finished.\n"); 462 463 afterIteration(jni); 464 465 found = getCounter(&objectCount); 466 NSK_DISPLAY1("Found tagged objects: %d\n", found); 467 468 modified = OBJ_MAX_COUNT - found; 469 if (modified > 0) { 470 NSK_COMPLAIN2("Tags were modified by other thread during heap iteration: %d of %d\n", 471 modified, OBJ_MAX_COUNT); 472 nsk_jvmti_setFailStatus(); 473 } 474 } 475 476 JNIEXPORT void JNICALL 477 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverInstancesOfClass( JNIEnv* jni, 478 jclass klass ) { 479 int modified = 0; 480 int found = 0; 481 482 if (!prepareToIteration(jni)) 483 return; 484 485 NSK_DISPLAY0("Calling IterateOverInstancesOfClass...\n"); 486 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverInstancesOfClass(debugeeClass, 487 JVMTI_HEAP_OBJECT_TAGGED, 488 heapObjectCallback, 489 NULL /*user_data*/))) { 490 nsk_jvmti_setFailStatus(); 491 } 492 NSK_DISPLAY0("IterateOverInstancesOfClass finished.\n"); 493 494 afterIteration(jni); 495 496 found = getCounter(&objectCount); 497 NSK_DISPLAY1("Found tagged objects: %d\n", found); 498 499 modified = OBJ_MAX_COUNT - found; 500 if (modified > 0) { 501 NSK_COMPLAIN2("Tags were modified by other thread during heap iteration: %d of %d\n", 502 modified, OBJ_MAX_COUNT); 503 nsk_jvmti_setFailStatus(); 504 } 505 } 506 507 JNIEXPORT void JNICALL 508 Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverObjectsReachableFromObject( JNIEnv* jni, 509 jclass klass ) { 510 jobject root = NULL; 511 int modified = 0; 512 int found = 0; 513 514 if (!NSK_JNI_VERIFY(jni, (root = 515 jni->GetStaticObjectField(debugeeClass, rootFieldID)) != NULL )) { 516 NSK_COMPLAIN0("GetStaticObjectField returned NULL for 'root' field value\n\n"); 517 nsk_jvmti_setFailStatus(); 518 return; 519 } 520 521 if (!prepareToIteration(jni)) 522 return; 523 524 NSK_DISPLAY0("Calling IterateOverObjectsReachableFromObject...\n"); 525 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverObjectsReachableFromObject(root, 526 objectReferenceCallback, 527 NULL /*user_data*/))) { 528 nsk_jvmti_setFailStatus(); 529 } 530 NSK_DISPLAY0("IterateOverObjectsReachableFromObject finished.\n"); 531 532 afterIteration(jni); 533 534 found = getCounter(&objectCount); 535 NSK_DISPLAY1("Found tagged objects: %d\n", found); 536 537 modified = OBJ_MAX_COUNT - found; 538 if (modified > 0) { 539 NSK_COMPLAIN2("Tags were modified by other thread during heap iteration: %d of %d\n", 540 modified, OBJ_MAX_COUNT); 541 nsk_jvmti_setFailStatus(); 542 } 543 } 544 545 static void JNICALL 546 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 547 548 NSK_DISPLAY0("Wait for debugee start\n\n"); 549 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 550 return; 551 552 NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_SIGNATURE); 553 debugeeClass = nsk_jvmti_classBySignature(DEBUGEE_SIGNATURE); 554 if (debugeeClass == NULL) { 555 nsk_jvmti_setFailStatus(); 556 return; 557 } 558 559 if (!NSK_JNI_VERIFY(jni, (debugeeClass = (jclass)jni->NewGlobalRef(debugeeClass)) != NULL)) 560 return; 561 562 NSK_DISPLAY1("Find ID of 'root' field: %s\n", ROOT_SIGNATURE); 563 if (!NSK_JNI_VERIFY(jni, (rootFieldID = 564 jni->GetStaticFieldID(debugeeClass, "root", ROOT_SIGNATURE)) != NULL )) { 565 nsk_jvmti_setFailStatus(); 566 return; 567 } 568 569 NSK_DISPLAY0("Let debugee to run test cases\n"); 570 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 571 return; 572 573 NSK_DISPLAY0("Wait for completion of test cases\n\n"); 574 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 575 return; 576 577 NSK_TRACE(jni->DeleteGlobalRef(debugeeClass)); 578 NSK_TRACE(jvmti->DestroyRawMonitor(counterMonitor_ptr)); 579 NSK_TRACE(jvmti->DestroyRawMonitor(startLock)); 580 NSK_TRACE(jvmti->DestroyRawMonitor(runLock)); 581 NSK_TRACE(jvmti->DestroyRawMonitor(endLock)); 582 583 NSK_DISPLAY0("Let debugee to finish\n"); 584 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 585 return; 586 } 587 588 #ifdef STATIC_BUILD 589 JNIEXPORT jint JNICALL Agent_OnLoad_ap04t003(JavaVM *jvm, char *options, void *reserved) { 590 return Agent_Initialize(jvm, options, reserved); 591 } 592 JNIEXPORT jint JNICALL Agent_OnAttach_ap04t003(JavaVM *jvm, char *options, void *reserved) { 593 return Agent_Initialize(jvm, options, reserved); 594 } 595 JNIEXPORT jint JNI_OnLoad_ap04t003(JavaVM *jvm, char *options, void *reserved) { 596 return JNI_VERSION_1_8; 597 } 598 #endif 599 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 600 /* init framework and parse options */ 601 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 602 return JNI_ERR; 603 604 /* create JVMTI environment */ 605 if (!NSK_VERIFY((jvmti = 606 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 607 return JNI_ERR; 608 609 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("counterMonitor", &counterMonitor_ptr))) { 610 return JNI_ERR; 611 } 612 613 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("startLock", &startLock))) { 614 return JNI_ERR; 615 } 616 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("runLock", &runLock))) { 617 return JNI_ERR; 618 } 619 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("endLock", &endLock))) { 620 return JNI_ERR; 621 } 622 623 memset(&caps, 0, sizeof(jvmtiCapabilities)); 624 caps.can_tag_objects = 1; 625 626 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 627 return JNI_ERR; 628 629 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps))) 630 return JNI_ERR; 631 632 if (!caps.can_tag_objects) 633 NSK_DISPLAY0("Warning: tagging objects is not available\n"); 634 635 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 636 return JNI_ERR; 637 NSK_DISPLAY0("agentProc has been set\n\n"); 638 639 return JNI_OK; 640 } 641 642 }