1 /* 2 * Copyright (c) 2007, 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 30 extern "C" { 31 32 /* ============================================================================= */ 33 34 static jlong timeout = 0; 35 36 #define DEBUGEE_CLASS_NAME "nsk/jvmti/unit/FollowReferences/followref002" 37 #define ROOT_OBJECT_CLASS_NAME "nsk/jvmti/unit/FollowReferences/followref002RootTestedClass" 38 #define ROOT_OBJECT_CLASS_SIG "L" ROOT_OBJECT_CLASS_NAME ";" 39 #define CHAIN_OBJECT_CLASS_NAME "nsk/jvmti/unit/FollowReferences/followref002TestedClass" 40 #define CHAIN_OBJECT_CLASS_SIG "L" CHAIN_OBJECT_CLASS_NAME ";" 41 42 #define OBJECT_FIELD_NAME "object" 43 #define REACHABLE_CHAIN_FIELD_NAME "reachableChain" 44 #define UNREACHABLE_CHAIN_FIELD_NAME "unreachableChain" 45 #define TAIL_FIELD_NAME "tail" 46 47 48 #define DEFAULT_CHAIN_LENGTH 3 49 50 typedef struct ObjectDescStruct { 51 jlong tag; /* Tag of the object */ 52 jlong exp_class_tag; /* Expected tag of the object class */ 53 jlong class_tag; /* Reported tag of the object class */ 54 jint exp_found; /* Expected number of iterations through the object */ 55 jint found; /* Reported number of iterations through the object */ 56 } ObjectDesc; 57 58 static int chainLength = 0; 59 static int objectsCount = 0; 60 static int fakeUserData = 0; 61 static int userDataError = 0; 62 63 static ObjectDesc* objectDescList = NULL; 64 65 static jlong rootClassTag = 9; 66 static jlong chainClassTag = 99; 67 static jlong rootObjectTag = 10; 68 static jlong chainObjectTag = 100; 69 70 static jvmtiHeapCallbacks heapCallbacks; 71 72 static const char* ref_kind_str[28] = { 73 "unknown_0", 74 "JVMTI_HEAP_REFERENCE_CLASS", 75 "JVMTI_HEAP_REFERENCE_FIELD", 76 "JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT", 77 "JVMTI_HEAP_REFERENCE_CLASS_LOADER", 78 "JVMTI_HEAP_REFERENCE_SIGNERS", 79 "JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN", 80 "JVMTI_HEAP_REFERENCE_INTERFACE", 81 "JVMTI_HEAP_REFERENCE_STATIC_FIELD", 82 "JVMTI_HEAP_REFERENCE_CONSTANT_POOL", 83 "unknown_10", "unknown_11", "unknown_12", 84 "unknown_13", "unknown_14", "unknown_15", "unknown_16", 85 "unknown_17", "unknown_18", "unknown_19", "unknown_20", 86 "JVMTI_HEAP_REFERENCE_JNI_GLOBAL", 87 "JVMTI_HEAP_REFERENCE_SYSTEM_CLASS", 88 "JVMTI_HEAP_REFERENCE_MONITOR", 89 "JVMTI_HEAP_REFERENCE_STACK_LOCAL", 90 "JVMTI_HEAP_REFERENCE_JNI_LOCAL", 91 "JVMTI_HEAP_REFERENCE_THREAD", 92 "JVMTI_HEAP_REFERENCE_OTHER" 93 }; 94 95 #define DEREF(ptr) (((ptr) == NULL ? 0 : *(ptr))) 96 97 /* ============================================================================= */ 98 99 /** Obtain chain of tested objects and tag them recursively. */ 100 static int getAndTagChainObjects( 101 jvmtiEnv* jvmti, 102 JNIEnv* jni, 103 jobject firstObject, 104 jfieldID firstField, 105 const char firstFieldName[], 106 jfieldID nextField, 107 const char nextFieldName[], 108 int count, 109 ObjectDesc objectDescList[], 110 jlong tag, 111 int reachable) 112 { 113 jobject obj = NULL; 114 jlong objTag = (reachable ? tag : -tag); 115 116 if (count <= 0) 117 return NSK_TRUE; 118 119 count--; 120 tag++; 121 122 if (!NSK_JNI_VERIFY(jni, (obj = 123 NSK_CPP_STUB3(GetObjectField, jni, firstObject, firstField)) != NULL)) { 124 nsk_jvmti_setFailStatus(); 125 return NSK_FALSE; 126 } 127 128 objectDescList[count].tag = objTag; 129 if (reachable) { 130 objectDescList[count].exp_found++; 131 } 132 133 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, obj, objTag))) { 134 nsk_jvmti_setFailStatus(); 135 } 136 printf(" tag=%-5ld object=0x%p\n", (long)objTag, (void*)obj); 137 fflush(0); 138 if (!getAndTagChainObjects(jvmti, jni, obj, 139 nextField, 140 nextFieldName, 141 nextField, 142 nextFieldName, 143 count, 144 objectDescList, 145 tag, 146 reachable)) { 147 return NSK_FALSE; 148 } 149 150 NSK_TRACE(NSK_CPP_STUB2(DeleteLocalRef, jni, obj)); 151 return NSK_TRUE; 152 } /* getAndTagChainObjects */ 153 154 /** Obtain all tested objects from debugee class and tag them recursively. */ 155 static int getAndTagTestedObjects( 156 jvmtiEnv* jvmti, 157 JNIEnv* jni, 158 int chainLength, 159 int* objectsCount, 160 ObjectDesc** objectDescList, 161 jobject* rootObject) 162 { 163 jclass debugeeClass = NULL; 164 jclass rootObjectClass = NULL; 165 jclass chainObjectClass = NULL; 166 167 jfieldID objectField = NULL; 168 jfieldID reachableChainField = NULL; 169 jfieldID unreachableChainField = NULL; 170 jfieldID tailField = NULL; 171 172 /* root object + reachable and unreachable object chains */ 173 *objectsCount = 1 + 2 * chainLength; 174 175 printf("Allocate memory for objects list: %d objects\n", *objectsCount); 176 fflush(0); 177 if (!NSK_JVMTI_VERIFY( 178 NSK_CPP_STUB3(Allocate, jvmti, (*objectsCount * sizeof(ObjectDesc)), 179 (unsigned char**)objectDescList))) { 180 nsk_jvmti_setFailStatus(); 181 return NSK_FALSE; 182 } 183 printf(" ... allocated array: 0x%p\n", (void*)objectDescList); 184 fflush(0); 185 186 { 187 int k; 188 for (k = 0; k < *objectsCount; k++) { 189 (*objectDescList)[k].tag = 0; 190 (*objectDescList)[k].exp_class_tag = chainClassTag; 191 (*objectDescList)[k].exp_found = 0; 192 (*objectDescList)[k].found = 0; 193 } 194 } 195 (*objectDescList)[0].exp_class_tag = rootClassTag; 196 197 printf("Find debugee class: %s\n", DEBUGEE_CLASS_NAME); 198 fflush(0); 199 if (!NSK_JNI_VERIFY(jni, (debugeeClass = 200 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) { 201 nsk_jvmti_setFailStatus(); 202 return NSK_FALSE; 203 } 204 printf(" ... found class: 0x%p\n", (void*)debugeeClass); 205 206 printf("Find root object class: %s\n", ROOT_OBJECT_CLASS_NAME); 207 fflush(0); 208 if (!NSK_JNI_VERIFY(jni, (rootObjectClass = 209 NSK_CPP_STUB2(FindClass, jni, ROOT_OBJECT_CLASS_NAME)) != NULL)) { 210 nsk_jvmti_setFailStatus(); 211 return NSK_FALSE; 212 } 213 printf(" ... found class: 0x%p\n", (void*)rootObjectClass); 214 215 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, rootObjectClass, rootClassTag))) { 216 nsk_jvmti_setFailStatus(); 217 } 218 printf(" tag=%-5ld rootClass=0x%p\n", (long)rootClassTag, (void*)rootObjectClass); 219 220 printf("Find chain object class: %s\n", CHAIN_OBJECT_CLASS_NAME); 221 fflush(0); 222 if (!NSK_JNI_VERIFY(jni, (chainObjectClass = 223 NSK_CPP_STUB2(FindClass, jni, CHAIN_OBJECT_CLASS_NAME)) != NULL)) { 224 nsk_jvmti_setFailStatus(); 225 return NSK_FALSE; 226 } 227 printf(" ... found class: 0x%p\n", (void*)chainObjectClass); 228 229 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, chainObjectClass, chainClassTag))) { 230 nsk_jvmti_setFailStatus(); 231 } 232 printf(" tag=%-5ld chainClass=0x%p\n", (long)chainClassTag, (void*)chainObjectClass); 233 234 printf("Find static field in debugee class: %s\n", OBJECT_FIELD_NAME); 235 fflush(0); 236 if (!NSK_JNI_VERIFY(jni, (objectField = 237 NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass, 238 OBJECT_FIELD_NAME, ROOT_OBJECT_CLASS_SIG)) != NULL)) { 239 nsk_jvmti_setFailStatus(); 240 return NSK_FALSE; 241 } 242 printf(" ... got fieldID: 0x%p\n", (void*)objectField); 243 244 printf("Find instance field in root object class: %s\n", REACHABLE_CHAIN_FIELD_NAME); 245 fflush(0); 246 if (!NSK_JNI_VERIFY(jni, (reachableChainField = 247 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass, 248 REACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) { 249 nsk_jvmti_setFailStatus(); 250 return NSK_FALSE; 251 } 252 printf(" ... got fieldID: 0x%p\n", (void*)reachableChainField); 253 254 printf("Find instance field in root object class: %s\n", UNREACHABLE_CHAIN_FIELD_NAME); 255 fflush(0); 256 if (!NSK_JNI_VERIFY(jni, (unreachableChainField = 257 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass, 258 UNREACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) { 259 nsk_jvmti_setFailStatus(); 260 return NSK_FALSE; 261 } 262 printf(" ... got fieldID: 0x%p\n", (void*)unreachableChainField); 263 264 printf("Find instance field in chain object class: %s\n", TAIL_FIELD_NAME); 265 fflush(0); 266 if (!NSK_JNI_VERIFY(jni, (tailField = 267 NSK_CPP_STUB4(GetFieldID, jni, chainObjectClass, 268 TAIL_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) { 269 nsk_jvmti_setFailStatus(); 270 return NSK_FALSE; 271 } 272 printf(" ... got fieldID: 0x%p\n", (void*)tailField); 273 274 printf("Get root object from static field: %s\n", OBJECT_FIELD_NAME); 275 fflush(0); 276 if (!NSK_JNI_VERIFY(jni, (*rootObject = 277 NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass, 278 objectField)) != NULL)) { 279 nsk_jvmti_setFailStatus(); 280 return NSK_FALSE; 281 } 282 printf(" ... got object: 0x%p\n", (void*)*rootObject); 283 fflush(0); 284 285 if (!NSK_JNI_VERIFY(jni, (*rootObject = 286 NSK_CPP_STUB2(NewGlobalRef, jni, *rootObject)) != NULL)) { 287 nsk_jvmti_setFailStatus(); 288 return NSK_FALSE; 289 } 290 printf(" ... global ref: 0x%p\n", (void*)*rootObject); 291 292 printf("Obtain and tag chain objects:\n"); 293 294 printf(" root tested object:\n"); 295 fflush(0); 296 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, *rootObject, rootObjectTag))) { 297 nsk_jvmti_setFailStatus(); 298 } 299 printf(" tag=%-5ld object=0x%p\n", (long)rootObjectTag, (void*)*rootObject); 300 301 (*objectDescList)[0].tag = rootObjectTag; 302 303 /* Root object must be referenced 1 time */ 304 (*objectDescList)[0].exp_found = 1; 305 306 /* Object with tag=101 must be referenced 2 times */ 307 (*objectDescList)[chainLength].exp_found = 1; 308 309 printf(" reachable objects chain: %d objects\n", chainLength); 310 fflush(0); 311 if (!getAndTagChainObjects(jvmti, jni, *rootObject, 312 reachableChainField, 313 REACHABLE_CHAIN_FIELD_NAME, 314 tailField, 315 TAIL_FIELD_NAME, 316 chainLength, 317 (*objectDescList) + 1, 318 chainObjectTag, 319 NSK_TRUE)) { 320 nsk_jvmti_setFailStatus(); 321 return NSK_FALSE; 322 } 323 324 printf(" unreachable objects chain: %d objects\n", chainLength); 325 if (!getAndTagChainObjects(jvmti, jni, *rootObject, 326 unreachableChainField, 327 UNREACHABLE_CHAIN_FIELD_NAME, 328 tailField, 329 TAIL_FIELD_NAME, 330 chainLength, 331 (*objectDescList) + 1 + chainLength, 332 chainObjectTag, 333 NSK_FALSE)) { 334 nsk_jvmti_setFailStatus(); 335 return NSK_FALSE; 336 } 337 338 return NSK_TRUE; 339 } /* getAndTagTestedObjects */ 340 341 /** Check if tagged objects were iterated. */ 342 static int checkTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, 343 int chainLength, ObjectDesc objectDescList[]) { 344 int success = NSK_TRUE; 345 int i, idx; 346 347 printf("Following tagged objects were iterated:\n"); 348 349 printf("Root tested object:\n"); 350 printf(" tag: %ld\n" 351 " expected to iterate: %d times\n" 352 " iterated: %d times\n", 353 (long) objectDescList[0].tag, 354 objectDescList[0].exp_found, 355 objectDescList[0].found); 356 if (objectDescList[0].found != objectDescList[0].exp_found) { 357 NSK_COMPLAIN1("Root tested object unexpectedly iterated %d times\n", 358 objectDescList[0].found); 359 nsk_jvmti_setFailStatus(); 360 } 361 362 printf("\nReachable objects:\n"); 363 fflush(0); 364 for (i = 0; i < chainLength; i++) { 365 idx = i + 1; 366 printf("Reachable object:\n" 367 " tag: %-3ld\n" 368 " expected to iterate: %d times\n" 369 " iterated: %d times\n", 370 (long) objectDescList[idx].tag, 371 objectDescList[idx].exp_found, 372 objectDescList[idx].found); 373 if (objectDescList[i + 1].found <= 0 && objectDescList[i + 1].exp_found > 0) { 374 NSK_COMPLAIN0("Reachable object was not iterated\n"); 375 nsk_jvmti_setFailStatus(); 376 } 377 if (objectDescList[idx].found != objectDescList[idx].exp_found) { 378 NSK_COMPLAIN0("Reachable object was iterated unexpected number of times\n"); 379 nsk_jvmti_setFailStatus(); 380 } 381 } 382 383 printf("\nUnreachable objects:\n"); 384 for (i = 0; i < chainLength; i++) { 385 idx = i + 1 + chainLength; 386 387 printf("Unreachable object:\n" 388 " tag: %ld\n" 389 " expected to iterate: %d times\n" 390 " iterated: %d times\n", 391 (long) objectDescList[idx].tag, 392 objectDescList[idx].exp_found, 393 objectDescList[idx].found); 394 if (objectDescList[idx].found > 0) { 395 NSK_COMPLAIN0("Unreachable object was iterated\n"); 396 nsk_jvmti_setFailStatus(); 397 } 398 fflush(0); 399 } 400 401 return NSK_TRUE; 402 } /* checkTestedObjects */ 403 404 /** Release references to the tested objects and free allocated memory. */ 405 static int releaseTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength, 406 ObjectDesc* objectDescList, jobject rootObject) { 407 if (rootObject != NULL) { 408 printf("Release object reference to root tested object: 0x%p\n", rootObject); 409 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, rootObject)); 410 } 411 412 if (objectDescList != NULL) { 413 printf("Deallocate objects list: 0x%p\n", (void*)objectDescList); 414 if (!NSK_JVMTI_VERIFY( 415 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)objectDescList))) { 416 nsk_jvmti_setFailStatus(); 417 } 418 } 419 420 fflush(0); 421 return NSK_TRUE; 422 } /* releaseTestedObjects */ 423 424 /* ============================================================================= */ 425 426 /** heapReferenceCallback for heap iterator. */ 427 jint JNICALL heapReferenceCallback( 428 jvmtiHeapReferenceKind reference_kind, 429 const jvmtiHeapReferenceInfo* reference_info, 430 jlong class_tag, 431 jlong referrer_class_tag, 432 jlong size, 433 jlong* tag_ptr, 434 jlong* referrer_tag_ptr, 435 jint length, 436 void* user_data) 437 { 438 jint referrer_index = 0; 439 jlong tag = DEREF(tag_ptr); 440 jlong ref_tag = DEREF(referrer_tag_ptr); 441 442 switch (reference_kind) { 443 case JVMTI_HEAP_REFERENCE_CONSTANT_POOL: 444 referrer_index = reference_info->constant_pool.index; 445 break; 446 case JVMTI_HEAP_REFERENCE_FIELD: 447 case JVMTI_HEAP_REFERENCE_STATIC_FIELD: 448 referrer_index = reference_info->field.index; 449 break; 450 case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT: 451 referrer_index = reference_info->array.index; 452 break; 453 case JVMTI_HEAP_REFERENCE_STACK_LOCAL: 454 referrer_index = reference_info->stack_local.slot; 455 /* Fall through */ 456 case JVMTI_HEAP_REFERENCE_JNI_LOCAL: 457 referrer_index |= reference_info->stack_local.depth << 16; 458 break; 459 default: 460 // TODO: check that realy should be done w/ other jvmtiHeapReferenceKind 461 break; 462 } 463 464 printf(" heapReferenceCallback: ref=%s, class_tag=%-3ld, tag=%-3ld," 465 " size=%-3ld, ref_tag=%-3ld, ref_idx=%#x\n", 466 ref_kind_str[reference_kind], 467 (long) class_tag, 468 (long) tag, 469 (long) size, 470 (long) ref_tag, 471 (int ) referrer_index); 472 fflush(0); 473 474 if (tag_ptr == NULL) { 475 NSK_COMPLAIN1("NULL tag_ptr is passed to heapReferenceCallback:" 476 " tag_ptr=0x%p\n", (void*)tag_ptr); 477 nsk_jvmti_setFailStatus(); 478 } 479 480 if (tag_ptr != NULL && *tag_ptr != 0) { 481 int found = 0; 482 int i; 483 484 for (i = 0; i < objectsCount; i++) { 485 if (*tag_ptr == objectDescList[i].tag) { 486 found++; 487 objectDescList[i].found++; 488 489 if (*tag_ptr < 0) { 490 NSK_COMPLAIN0("Unreachable tagged object is passed to heapReferenceCallback\n"); 491 nsk_jvmti_setFailStatus(); 492 } 493 break; 494 } 495 } 496 497 if (reference_kind != JVMTI_HEAP_REFERENCE_CLASS && found <= 0) { 498 NSK_COMPLAIN0("Unknown tagged object is passed to heapReferenceCallback\n"); 499 nsk_jvmti_setFailStatus(); 500 } 501 } 502 503 if (user_data != &fakeUserData && !userDataError) { 504 NSK_COMPLAIN2("Unexpected user_data is passed to heapReferenceCallback:\n" 505 " expected: 0x%p\n" 506 " actual: 0x%p\n", 507 user_data, 508 &fakeUserData); 509 nsk_jvmti_setFailStatus(); 510 userDataError++; 511 } 512 513 switch (reference_kind) { 514 int i; 515 case JVMTI_HEAP_REFERENCE_CLASS: { 516 if (tag == 0) { 517 break; 518 } 519 if (tag != rootClassTag && tag != chainClassTag) { 520 NSK_COMPLAIN0("Unknown tagged class is passed to heapReferenceCallback\n"); 521 nsk_jvmti_setFailStatus(); 522 } 523 for (i = 0; i < objectsCount; i++) { 524 if (ref_tag == objectDescList[i].tag) { 525 if (objectDescList[i].exp_class_tag != tag) { 526 NSK_COMPLAIN2("Wrong tag in heapReferenceCallback/JVMTI_HEAP_REFERENCE_CLASS:\n" 527 "Expected: %-3ld\n" 528 "Passed: %-3ld\n", 529 objectDescList[i].exp_class_tag, 530 tag); 531 nsk_jvmti_setFailStatus(); 532 } 533 break; 534 } 535 } 536 break; 537 } 538 case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: 539 case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: 540 case JVMTI_HEAP_REFERENCE_MONITOR: 541 case JVMTI_HEAP_REFERENCE_STACK_LOCAL: 542 case JVMTI_HEAP_REFERENCE_JNI_LOCAL: 543 case JVMTI_HEAP_REFERENCE_THREAD: 544 case JVMTI_HEAP_REFERENCE_OTHER: { 545 NSK_COMPLAIN1("This reference kind was not expected: %s\n", 546 ref_kind_str[reference_kind]); 547 fflush(0); 548 nsk_jvmti_setFailStatus(); 549 return 0; 550 } 551 default: 552 // TODO: check that realy should be done w/ other jvmtiHeapReferenceKind 553 break; 554 } 555 return JVMTI_VISIT_OBJECTS; 556 } 557 558 jint JNICALL primitiveFieldCallback( 559 jvmtiHeapReferenceKind reference_kind, 560 const jvmtiHeapReferenceInfo* reference_info, 561 jlong class_tag, 562 jlong* tag_ptr, 563 jvalue value, 564 jvmtiPrimitiveType value_type, 565 void* user_data) 566 { 567 printf(" primitiveFieldCallback: ref=%s, class_tag=%-3ld, tag=%-3ld, type=%c\n", 568 ref_kind_str[reference_kind], 569 (long) class_tag, 570 (long) DEREF(tag_ptr), 571 (int ) value_type); 572 fflush(0); 573 return 0; 574 } 575 576 jint JNICALL arrayPrimitiveValueCallback( 577 jlong class_tag, 578 jlong size, 579 jlong* tag_ptr, 580 jint element_count, 581 jvmtiPrimitiveType element_type, 582 const void* elements, 583 void* user_data) 584 { 585 printf(" arrayPrimitiveValueCallback: class_tag=%-3ld, tag=%-3ld, len=%d, type=%c\n", 586 (long) class_tag, 587 (long) DEREF(tag_ptr), 588 (int ) element_count, 589 (int ) element_type); 590 fflush(0); 591 return 0; 592 } 593 594 jint JNICALL stringPrimitiveValueCallback( 595 jlong class_tag, 596 jlong size, 597 jlong* tag_ptr, 598 const jchar* value, 599 jint value_length, 600 void* user_data) 601 { 602 printf("stringPrimitiveValueCallback: class_tag=%-3ld, tag=%-3ld, len=%d\n", 603 (long) class_tag, 604 (long) DEREF(tag_ptr), 605 (int ) value_length); 606 fflush(0); 607 return 0; 608 } 609 610 /* ============================================================================= */ 611 612 /** Agent algorithm. */ 613 static void JNICALL 614 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 615 jobject rootObject = NULL; 616 617 printf("Wait for tested objects created\n"); 618 fflush(0); 619 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) { 620 return; 621 } 622 623 printf(">>> Obtain and tag tested objects from debugee class\n"); 624 fflush(0); 625 { 626 if (!NSK_VERIFY(getAndTagTestedObjects(jvmti, jni, 627 chainLength, &objectsCount, 628 &objectDescList, &rootObject))) { 629 return; 630 } 631 } 632 633 printf(">>> Let debugee to clean links to unreachable objects\n"); 634 fflush(0); 635 { 636 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) { 637 return; 638 } 639 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) { 640 return; 641 } 642 } 643 644 printf("\n\n>>> Start 1-st iteration for root tested object: 0x%p\n", rootObject); 645 fflush(0); 646 { 647 jint heap_filter = JVMTI_HEAP_FILTER_UNTAGGED | JVMTI_HEAP_FILTER_CLASS_UNTAGGED; 648 if (!NSK_JVMTI_VERIFY( 649 NSK_CPP_STUB6(FollowReferences, jvmti, 650 heap_filter, 651 (jclass) NULL, /* class */ 652 rootObject, /* initial_object */ 653 &heapCallbacks, 654 (const void *) &fakeUserData))) 655 { 656 nsk_jvmti_setFailStatus(); 657 return; 658 } 659 } 660 661 printf(">>> Check if reachable objects were iterated\n"); 662 fflush(0); 663 { 664 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) { 665 nsk_jvmti_setFailStatus(); 666 } 667 } 668 669 670 { /* Reinstall the expectations */ 671 int k; 672 for (k = 0; k < objectsCount; k++) { 673 (objectDescList)[k].exp_found = 0; 674 (objectDescList)[k].found = 0; 675 } 676 } 677 678 printf("\n\n>>> Start 2-nd iteration for root tested object: 0x%p\n", rootObject); 679 fflush(0); 680 { 681 /* This time everythig is filtered out */ 682 jint heap_filter = JVMTI_HEAP_FILTER_UNTAGGED | JVMTI_HEAP_FILTER_CLASS_UNTAGGED | 683 JVMTI_HEAP_FILTER_TAGGED | JVMTI_HEAP_FILTER_CLASS_TAGGED; 684 if (!NSK_JVMTI_VERIFY( 685 NSK_CPP_STUB6(FollowReferences, jvmti, 686 heap_filter, 687 (jclass) NULL, /* class */ 688 rootObject, /* initial_object */ 689 &heapCallbacks, 690 (const void *) &fakeUserData))) 691 { 692 nsk_jvmti_setFailStatus(); 693 return; 694 } 695 } 696 697 printf(">>> Check if reachable objects were not reported this time\n"); 698 fflush(0); 699 { 700 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) { 701 nsk_jvmti_setFailStatus(); 702 } 703 } 704 705 printf(">>> Clean used data\n"); 706 fflush(0); 707 { 708 if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, chainLength, objectDescList, rootObject))) { 709 return; 710 } 711 } 712 713 printf("Let debugee to finish\n"); 714 fflush(0); 715 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 716 return; 717 } 718 719 /* ============================================================================= */ 720 721 /** Agent library initialization. */ 722 #ifdef STATIC_BUILD 723 JNIEXPORT jint JNICALL Agent_OnLoad_followref002(JavaVM *jvm, char *options, void *reserved) { 724 return Agent_Initialize(jvm, options, reserved); 725 } 726 JNIEXPORT jint JNICALL Agent_OnAttach_followref002(JavaVM *jvm, char *options, void *reserved) { 727 return Agent_Initialize(jvm, options, reserved); 728 } 729 JNIEXPORT jint JNI_OnLoad_followref002(JavaVM *jvm, char *options, void *reserved) { 730 return JNI_VERSION_1_8; 731 } 732 #endif 733 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 734 jvmtiEnv* jvmti = NULL; 735 736 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 737 return JNI_ERR; 738 739 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 740 741 chainLength = nsk_jvmti_findOptionIntValue("objects", DEFAULT_CHAIN_LENGTH); 742 if (!NSK_VERIFY(chainLength > 0)) 743 return JNI_ERR; 744 745 if (!NSK_VERIFY((jvmti = 746 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 747 return JNI_ERR; 748 749 { 750 jvmtiCapabilities caps; 751 752 memset(&caps, 0, sizeof(caps)); 753 caps.can_tag_objects = 1; 754 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) { 755 return JNI_ERR; 756 } 757 } 758 759 /* Setting Heap Callbacks */ 760 heapCallbacks.heap_iteration_callback = NULL; 761 heapCallbacks.heap_reference_callback = heapReferenceCallback; 762 heapCallbacks.primitive_field_callback = primitiveFieldCallback; 763 heapCallbacks.array_primitive_value_callback = arrayPrimitiveValueCallback; 764 heapCallbacks.string_primitive_value_callback = stringPrimitiveValueCallback; 765 766 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 767 return JNI_ERR; 768 769 return JNI_OK; 770 } 771 772 /* ============================================================================= */ 773 774 }