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