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