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