1 /*
   2  * Copyright (c) 2013, 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 #include <wchar.h>
  24 #include <string.h>
  25 #include <stdlib.h>
  26 
  27 #include "jvmti.h"
  28 #include "jni_tools.h"
  29 #include "jvmti_tools.h"
  30 #include "agent_common.h"
  31 
  32 extern "C" {
  33 
  34 #define STATIC_FIELD 0x0008
  35 
  36 ///amount of objects to be tagged
  37 #define TEST_OBJECTS_COUNT 4
  38 
  39 ///expected amount of times object will bre ported by callbacks
  40 #define PRIMITIVE_OCCURANCE_COUNT 1
  41 #define STRING_OCCURANCE_COUNT 2
  42 #define PRIMITIVE_ARRAY_OCCURANCE_COUNT 2
  43 #define NONPRIMITIVE_OCCURANCE_COUNT 1
  44 
  45 
  46 /**
  47   tag format
  48 
  49   63      35   32      16         0
  50   |1       |type|obj idx|field idx|
  51 
  52 */
  53 
  54 #define TAG_TYPE_PRIMITIVE 0
  55 #define TAG_TYPE_STRING 1
  56 #define TAG_TYPE_ARRAY 2
  57 #define TAG_TYPE_OBJECT 3
  58 
  59 #define ENCODE_TAG(type,obj,fld) (0x8000000000000000ULL|(((jlong)type)<<32)|(((jlong)obj)<<16)|fld)
  60 
  61 #define DECODE_TYPE(tag) ((tag>>32)&0x0FFFF)
  62 #define DECODE_OBJECT(tag) ((tag>>16)&0x0FFFF)
  63 #define DECODE_FIELD(tag) (tag&0x0FFFF)
  64 
  65 ///expected values
  66 #define BOOLEAN JNI_FALSE
  67 #define BYTE 0xB
  68 #define CHAR 'z'
  69 #define SHORT 0xB00
  70 #define INT ((int)0xDEADBEEF)
  71 #define LONG 0xDEADBEEFDEADLL
  72 #define FLOAT 3.1416f
  73 #define DOUBLE 3.14159265
  74 
  75 #define ARRAY_LENGTH 5
  76 
  77 static const wchar_t *STRING = L"I hope you'll find me in the heap!";
  78 static jboolean BOOLEAN_ARRAY[] = {JNI_TRUE, JNI_TRUE, JNI_FALSE, JNI_TRUE, JNI_FALSE};
  79 static jbyte BYTE_ARRAY[] = {BYTE, BYTE+1, BYTE+2, BYTE+3, BYTE+4};
  80 static jchar CHAR_ARRAY[] = {CHAR, CHAR+1, CHAR+2, CHAR+3, CHAR+4};
  81 static jshort SHORT_ARRAY[] = {SHORT, SHORT+1, SHORT+2, SHORT+3, SHORT+4};
  82 static jint INT_ARRAY[] = {INT, INT+1, INT+2, INT+3, INT+4};
  83 static jlong LONG_ARRAY[] = {LONG, LONG+1, LONG+2, LONG+3, LONG+4};
  84 static jfloat FLOAT_ARRAY[] = {FLOAT, FLOAT+1, FLOAT+2, FLOAT+3, FLOAT+4};
  85 static jdouble DOUBLE_ARRAY[] = {DOUBLE, DOUBLE+1, DOUBLE+2, DOUBLE+3, DOUBLE+4};
  86 
  87 static long timeout = 0;
  88 
  89 ///information about field
  90 typedef struct {
  91   char *name;
  92   char *signature;
  93   int found;
  94   int collected;
  95   int primitive;
  96 } field_info_t;
  97 
  98 ///information about object
  99 typedef struct {
 100   char *name;
 101   jint fields_count;
 102   field_info_t *fields;
 103   int collected;
 104 } object_info_t;
 105 
 106 static object_info_t objects_info[TEST_OBJECTS_COUNT];
 107 
 108 #define className "nsk/jvmti/IterateThroughHeap/callbacks/Callbacks"
 109 #define fieldName "testObjects"
 110 #define fieldSig "[Ljava/lang/Object;"
 111 
 112 // Check if the signature is signature of primitive type.
 113 jboolean is_primitive_type(const char *signature) {
 114   if(!strcmp(signature,"C")
 115      || !strcmp(signature, "B")
 116      || !strcmp(signature, "S")
 117      || !strcmp(signature, "I")
 118      || !strcmp(signature, "J")
 119      || !strcmp(signature, "F")
 120      || !strcmp(signature, "D")
 121      || !strcmp(signature, "Z"))
 122     return JNI_TRUE;
 123   return JNI_FALSE;
 124 }
 125 
 126 // For given signature find expected tag type
 127 int get_tag_type(const char *signature) {
 128   if(is_primitive_type(signature)) {
 129     return TAG_TYPE_PRIMITIVE;
 130   } else if(signature[0]=='[' && is_primitive_type(signature+1)) {
 131     return TAG_TYPE_ARRAY;
 132   } else if(!strcmp(signature, "Ljava/lang/String;")) {
 133     return TAG_TYPE_STRING;
 134   } else {
 135     return TAG_TYPE_OBJECT;
 136   }
 137 }
 138 
 139 /**
 140   * Check value corectness accordning to it's type.
 141   * Returns 0 if value matched with expected.
 142   */
 143 jboolean verify_value(jvalue value, jvmtiPrimitiveType type) {
 144   switch(type) {
 145   case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
 146     return value.z==BOOLEAN;
 147   case JVMTI_PRIMITIVE_TYPE_BYTE:
 148     return value.b==BYTE;
 149   case JVMTI_PRIMITIVE_TYPE_CHAR:
 150     return value.c==CHAR;
 151   case JVMTI_PRIMITIVE_TYPE_SHORT:
 152     return value.s==SHORT;
 153   case JVMTI_PRIMITIVE_TYPE_INT:
 154     return value.i==INT;
 155   case JVMTI_PRIMITIVE_TYPE_LONG:
 156     return value.j==LONG;
 157   case JVMTI_PRIMITIVE_TYPE_FLOAT:
 158     return value.f==FLOAT;
 159   case JVMTI_PRIMITIVE_TYPE_DOUBLE:
 160     return value.d==DOUBLE;
 161   default:
 162     NSK_COMPLAIN1("Unknown type: %X.",type);
 163     return JNI_FALSE;
 164   }
 165 }
 166 
 167 // Check that array values are correct depending on type of elements
 168 jboolean verify_array(const void *array, jvmtiPrimitiveType type, jint length) {
 169   void *expected_array;
 170   switch(type) {
 171   case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
 172     expected_array = (void*)BOOLEAN_ARRAY;
 173     break;
 174   case JVMTI_PRIMITIVE_TYPE_CHAR:
 175     expected_array = (void*)CHAR_ARRAY;
 176     break;
 177   case JVMTI_PRIMITIVE_TYPE_BYTE:
 178     expected_array = (void*)BYTE_ARRAY;
 179     break;
 180   case JVMTI_PRIMITIVE_TYPE_SHORT:
 181     expected_array = (void*)SHORT_ARRAY;
 182     break;
 183   case JVMTI_PRIMITIVE_TYPE_INT:
 184     expected_array = (void*)INT_ARRAY;
 185     break;
 186   case JVMTI_PRIMITIVE_TYPE_LONG:
 187     expected_array = (void*)LONG_ARRAY;
 188     break;
 189   case JVMTI_PRIMITIVE_TYPE_FLOAT:
 190     expected_array = (void*)FLOAT_ARRAY;
 191     break;
 192   case JVMTI_PRIMITIVE_TYPE_DOUBLE:
 193     expected_array = (void*)DOUBLE_ARRAY;
 194     break;
 195   default:
 196     NSK_COMPLAIN0("Unexpected type of array's elements.\n");
 197     return JNI_FALSE;
 198   }
 199   return memcmp(expected_array,array,length) == 0;
 200 }
 201 
 202 jint JNICALL field_callback(jvmtiHeapReferenceKind kind,
 203                             const jvmtiHeapReferenceInfo* info,
 204                             jlong object_class_tag,
 205                             jlong* object_tag_ptr,
 206                             jvalue value,
 207                             jvmtiPrimitiveType value_type,
 208                             void* user_data) {
 209   jlong tag;
 210   tag = *object_tag_ptr;
 211 
 212   // skip all non-tagged fields as well as fields of tagged objects
 213   if(tag == 0 ||
 214      DECODE_TYPE(tag) == TAG_TYPE_OBJECT ||
 215      DECODE_TYPE(tag) == TAG_TYPE_STRING) {
 216     return 0;
 217   } else if(DECODE_TYPE(tag) != TAG_TYPE_PRIMITIVE) {
 218     NSK_COMPLAIN3("jvmtiPrimitiveFieldCallback was invoked for an object with "
 219                   "non-primitive field tag (0x%lX) corresponging to %s::%s.\n",
 220                   DECODE_TYPE(tag),
 221                   objects_info[DECODE_OBJECT(tag)].name,
 222                   objects_info[DECODE_OBJECT(tag)].fields[DECODE_FIELD(tag)].name);
 223     nsk_jvmti_setFailStatus();
 224     return 0;
 225   }
 226 
 227   objects_info[DECODE_OBJECT(tag)].fields[info->field.index].found++;
 228 
 229   if(!verify_value(value, value_type)) {
 230     NSK_COMPLAIN2("Field %s::%s has unexpected value.\n",
 231                   objects_info[DECODE_OBJECT(tag)].name,
 232                   objects_info[DECODE_OBJECT(tag)].fields[info->field.index].name);
 233     nsk_jvmti_setFailStatus();
 234   }
 235   return 0;
 236 }
 237 
 238 jint JNICALL string_callback(jlong class_tag,
 239                              jlong size,
 240                              jlong* tag_ptr,
 241                              const jchar* value,
 242                              jint value_length,
 243                              void* user_data) {
 244   int matched = 1;
 245   int i;
 246 
 247   //skip all untegged strings
 248   if(*tag_ptr==0) {
 249     return 0;
 250   } else if(DECODE_TYPE(*tag_ptr) != TAG_TYPE_STRING) {
 251     NSK_COMPLAIN2("jvmtiStringPrimitiveValueCallback was invoked for an object "
 252                   "with non-string tag corresponding to %s::%s.\n",
 253                   objects_info[DECODE_OBJECT(*tag_ptr)].name,
 254                   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].name);
 255     return 0;
 256   }
 257 
 258   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].found++;
 259 
 260   //check that reported length is the same as expected
 261   if(value_length != (jint) wcslen(STRING)) {
 262     NSK_COMPLAIN4("Length of reported string %s::%s is %d while %d is expected.\n",
 263                   objects_info[DECODE_OBJECT(*tag_ptr)].name,
 264                   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].name,
 265                   value_length,
 266                   wcslen(STRING));
 267     nsk_jvmti_setFailStatus();
 268     return 0;
 269   }
 270 
 271   //compare reported value with expected one
 272   for(i = 0; i<value_length && matched; i++) {
 273     matched = value[i] == STRING[i];
 274   }
 275 
 276   if(!matched) {
 277     NSK_COMPLAIN2("Value of field %s::%s has unexpected value.\n",
 278                   objects_info[DECODE_OBJECT(*tag_ptr)].name,
 279                   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].name);
 280 
 281     nsk_jvmti_setFailStatus();
 282   }
 283   return 0;
 284 }
 285 
 286 jint JNICALL array_callback(jlong class_tag,
 287                             jlong size,
 288                             jlong* tag_ptr,
 289                             jint element_count,
 290                             jvmtiPrimitiveType element_type,
 291                             const void* elements,
 292                             void* user_data) {
 293   //skip untegged arrays
 294   if(*tag_ptr == 0) {
 295     return 0;
 296   } else if(DECODE_TYPE(*tag_ptr) != TAG_TYPE_ARRAY) {
 297     NSK_COMPLAIN2("jvmtiArrayPrimitiveValueCallbak was invoked for object "
 298                   "with non-array tag corresponding to %s::%s.\n",
 299                   objects_info[DECODE_OBJECT(*tag_ptr)].name,
 300                   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].name);
 301     nsk_jvmti_setFailStatus();
 302     return 0;
 303   }
 304 
 305   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].found++;
 306 
 307   //check if reported length is the same as expected
 308   if(element_count != ARRAY_LENGTH) {
 309     NSK_COMPLAIN4("Length of array %s::%s is %d while %d is expected.\n",
 310                   objects_info[DECODE_OBJECT(*tag_ptr)].name,
 311                   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].name,
 312                   element_count,
 313                   ARRAY_LENGTH);
 314     nsk_jvmti_setFailStatus();
 315   } else if(!verify_array(elements, element_type, element_count)) {
 316     //compare array with expected one
 317     NSK_COMPLAIN2("Value of field %s::%s has unexpected value.\n",
 318                   objects_info[DECODE_OBJECT(*tag_ptr)].name,
 319                   objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].name);
 320     nsk_jvmti_setFailStatus();
 321   }
 322   return 0;
 323 }
 324 
 325 jint JNICALL heap_callback(jlong class_tag,
 326                            jlong size,
 327                            jlong* tag_ptr,
 328                            jint length,
 329                            void* user_data) {
 330   //skip untagged objects
 331   if(*tag_ptr == 0) {
 332     return 0;
 333   }
 334 
 335   if(DECODE_TYPE(*tag_ptr) != TAG_TYPE_PRIMITIVE) {
 336     objects_info[DECODE_OBJECT(*tag_ptr)].fields[DECODE_FIELD(*tag_ptr)].found++;
 337   }
 338 
 339   return 0;
 340 }
 341 
 342 JNIEXPORT void JNICALL
 343 object_free_callback(jvmtiEnv* jvmti, jlong tag) {
 344   if(DECODE_TYPE(tag)==TAG_TYPE_PRIMITIVE) {
 345     int object = DECODE_OBJECT(tag);
 346     objects_info[object].collected = 1;
 347     NSK_DISPLAY1("Object %s collected.\n",
 348                  objects_info[object].name);
 349   } else {
 350     int object = DECODE_OBJECT(tag);
 351     int field = DECODE_FIELD(tag);
 352     objects_info[object].fields[field].collected = 1;
 353     NSK_DISPLAY2("Field %s of intance of %s collected.\n",
 354                  objects_info[object].fields[field].name,
 355                  objects_info[object].name);
 356   }
 357 }
 358 
 359 /**
 360  * Read array of test objects.
 361  * Tag each of these objjects, their classes, non-primitive fields and non-primitive fields classes.
 362  * Each tag has following format:
 363  * In case when some class already tagged old tag is used.
 364  */
 365 int tag_objects(jvmtiEnv *jvmti, JNIEnv *jni) {
 366   jclass debugee;
 367   jfieldID testObjectsField;
 368   jobjectArray testObjects;
 369   int object;
 370 
 371   if(!NSK_VERIFY(NULL != (debugee = jni->FindClass(className))))
 372     return JNI_ERR;
 373 
 374   if(!NSK_VERIFY(NULL != (testObjectsField = jni->GetStaticFieldID(debugee, fieldName, fieldSig))))
 375     return JNI_ERR;
 376 
 377   if(!NSK_VERIFY(NULL != (testObjects = (jobjectArray)(jni->GetStaticObjectField(
 378           debugee, testObjectsField)))))
 379     return JNI_ERR;
 380 
 381   // For each of test objects tag every field
 382   for(object = 0; object<TEST_OBJECTS_COUNT; object++) {
 383     jobject target;
 384     jclass targetClass;
 385     jfieldID *targetFields;
 386     jint field;
 387 
 388     memset(&objects_info[object],0,sizeof(object_info_t));
 389     if(!NSK_VERIFY(NULL != (target = jni->GetObjectArrayElement(testObjects, object))))
 390       return JNI_ERR;
 391 
 392     if(!NSK_VERIFY(NULL != (targetClass = jni->GetObjectClass(target))))
 393       return JNI_ERR;
 394 
 395     if(!NSK_JVMTI_VERIFY(jvmti->GetClassSignature(targetClass, &(objects_info[object].name), NULL)))
 396       return JNI_ERR;
 397 
 398     if(!NSK_JVMTI_VERIFY(jvmti->GetClassFields(
 399             targetClass, &(objects_info[object].fields_count), &targetFields)))
 400       return JNI_ERR;
 401 
 402     objects_info[object].fields = (field_info_t*)calloc(objects_info[object].fields_count,sizeof(field_info_t));
 403 
 404     // Iterate over fields, collect info about it and tag non primitive fields.
 405     for(field = 0; field < objects_info[object].fields_count; field++) {
 406       if(!NSK_JVMTI_VERIFY(jvmti->GetFieldName(targetClass,
 407                                                targetFields[field],
 408                                                &objects_info[object].fields[field].name,
 409                                                &objects_info[object].fields[field].signature,
 410                                                NULL)))
 411         return JNI_ERR;
 412       if(is_primitive_type(objects_info[object].fields[field].signature)) {
 413         objects_info[object].fields[field].primitive = 1;
 414       } else {
 415         jint modifiers;
 416         jobject value;
 417         int tag_type = get_tag_type(objects_info[object].fields[field].signature);
 418         if(!NSK_JVMTI_VERIFY(jvmti->GetFieldModifiers(
 419                 targetClass, targetFields[field], &modifiers))) {
 420           return JNI_ERR;
 421         }
 422         if(modifiers & STATIC_FIELD) {
 423           if(!NSK_VERIFY(NULL != (value = jni->GetStaticObjectField(targetClass,
 424                                                                     targetFields[field])))) {
 425             return JNI_ERR;
 426           }
 427         } else {
 428           if(!NSK_VERIFY(NULL != (value = jni->GetObjectField(target, targetFields[field])))) {
 429             return JNI_ERR;
 430           }
 431         }
 432         //tag field's value
 433         if(!NSK_JVMTI_VERIFY(jvmti->SetTag(value, ENCODE_TAG(tag_type,object,field)))) {
 434           return JNI_ERR;
 435         }
 436         //remove local reference so object will have a chance to become unreachable
 437         jni->DeleteLocalRef((jobject)value);
 438       }
 439     }
 440 
 441     // tag class and it's instance to pass this tag into primitive field callback
 442     if(!NSK_JVMTI_VERIFY(jvmti->SetTag(target, ENCODE_TAG(TAG_TYPE_PRIMITIVE,object,0))))
 443       return JNI_ERR;
 444     if(!NSK_JVMTI_VERIFY(jvmti->SetTag(targetClass, ENCODE_TAG(TAG_TYPE_PRIMITIVE,object,0))))
 445       return JNI_ERR;
 446 
 447     NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)targetFields));
 448 
 449     jni->DeleteLocalRef((jobject)target);
 450     jni->DeleteLocalRef((jobject)targetClass);
 451   }
 452 
 453   jni->DeleteLocalRef((jobject)testObjects);
 454 
 455   return JNI_OK;
 456 }
 457 
 458 //free all resources allocated in tag_objects
 459 void release_object_info(jvmtiEnv *jvmti, JNIEnv *jni) {
 460   int object;
 461   int field;
 462   for(object = 0; object < TEST_OBJECTS_COUNT; object++) {
 463     for(field = 0; field < objects_info[object].fields_count; field++) {
 464       jvmti->Deallocate((unsigned char*)objects_info[object].fields[field].name);
 465       jvmti->Deallocate((unsigned char*)objects_info[object].fields[field].signature);
 466     }
 467     jvmti->Deallocate((unsigned char*)objects_info[object].name);
 468     free(objects_info[object].fields);
 469   }
 470 }
 471 
 472 // Check that every field was found expected amount of times and reset information about that.
 473 void verify_objects() {
 474   int object;
 475   int field;
 476   for(object = 0; object < TEST_OBJECTS_COUNT; object++) {
 477     for(field = 0; field < objects_info[object].fields_count; field++) {
 478       // If primitive field of object that was not collected or
 479       // non primitive field that was not collected was not found
 480       // expected amount of times, than test failed.
 481       if((objects_info[object].fields[field].primitive && !objects_info[object].collected)
 482          || !objects_info[object].fields[field].collected) {
 483         int expected = 0;
 484         switch(get_tag_type(objects_info[object].fields[field].signature)) {
 485         case TAG_TYPE_STRING:
 486           expected = STRING_OCCURANCE_COUNT;
 487           break;
 488         case TAG_TYPE_ARRAY:
 489           expected = PRIMITIVE_ARRAY_OCCURANCE_COUNT;
 490           break;
 491         case TAG_TYPE_PRIMITIVE:
 492           expected = PRIMITIVE_OCCURANCE_COUNT;
 493           break;
 494         default:
 495           expected = NONPRIMITIVE_OCCURANCE_COUNT;
 496           break;
 497         }
 498         if(expected != objects_info[object].fields[field].found) {
 499           NSK_COMPLAIN4("Field %s::%s expected to be found %d times, "
 500                         "but it was found %d times.\n",
 501                         objects_info[object].name,
 502                         objects_info[object].fields[field].name,
 503                         expected,
 504                         objects_info[object].fields[field].found);
 505         }
 506       }
 507       objects_info[object].fields[field].found = 0;
 508     }
 509   }
 510 }
 511 
 512 static void JNICALL
 513 agent(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 514   jvmtiEvent event = JVMTI_EVENT_OBJECT_FREE;
 515   jvmtiHeapCallbacks primitive_callbacks;
 516 
 517   NSK_DISPLAY0("Waiting debugee.\n");
 518   if(!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL))) {
 519     return;
 520   }
 521   if(!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
 522     return;
 523   }
 524 
 525   NSK_DISPLAY0("Tagging fields.\n");
 526   if(!NSK_VERIFY(JNI_OK==tag_objects(jvmti, jni))) {
 527     return;
 528   }
 529 
 530   memset(&primitive_callbacks, 0, sizeof(jvmtiHeapCallbacks));
 531   primitive_callbacks.primitive_field_callback = &field_callback;
 532   primitive_callbacks.array_primitive_value_callback = &array_callback;
 533   primitive_callbacks.string_primitive_value_callback = &string_callback;
 534   primitive_callbacks.heap_iteration_callback = &heap_callback;
 535 
 536   NSK_DISPLAY0("Iterating over reachable objects.\n");
 537   if(!NSK_JVMTI_VERIFY(jvmti->IterateThroughHeap(0, NULL, &primitive_callbacks, NULL))) {
 538     nsk_jvmti_setFailStatus();
 539     return;
 540   }
 541 
 542   NSK_DISPLAY0("Verifying that all filds were found.\n");
 543   verify_objects();
 544 
 545   if(!NSK_VERIFY(nsk_jvmti_resumeSync())) {
 546     return;
 547   }
 548 
 549   if(!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
 550     return;
 551   }
 552 
 553   NSK_DISPLAY0("Iterating over unreachable objects.\n");
 554   if(!NSK_JVMTI_VERIFY(jvmti->IterateThroughHeap(0, NULL, &primitive_callbacks, NULL))) {
 555     nsk_jvmti_setFailStatus();
 556     return;
 557   }
 558 
 559   NSK_DISPLAY0("Verifying that all filds were found.\n");
 560   verify_objects();
 561 
 562   if(!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL))) {
 563     return;
 564   }
 565 
 566   release_object_info(jvmti, jni);
 567 
 568   if(!NSK_VERIFY(nsk_jvmti_resumeSync()))
 569     return;
 570 }
 571 
 572 #ifdef STATIC_BUILD
 573 JNIEXPORT jint JNICALL Agent_OnLoad_Callbacks(JavaVM *jvm, char *options, void *reserved) {
 574     return Agent_Initialize(jvm, options, reserved);
 575 }
 576 JNIEXPORT jint JNICALL Agent_OnAttach_Callbacks(JavaVM *jvm, char *options, void *reserved) {
 577     return Agent_Initialize(jvm, options, reserved);
 578 }
 579 JNIEXPORT jint JNI_OnLoad_Callbacks(JavaVM *jvm, char *options, void *reserved) {
 580     return JNI_VERSION_1_8;
 581 }
 582 #endif
 583 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 584   jvmtiEnv *jvmti;
 585   jvmtiCapabilities caps;
 586   jvmtiEventCallbacks event_callbacks;
 587 
 588   if(!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) {
 589     return JNI_ERR;
 590   }
 591 
 592   nsk_jvmti_parseOptions(options);
 593 
 594   timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 595 
 596   memset(&caps, 0, sizeof(caps));
 597   caps.can_tag_objects = 1;
 598   caps.can_generate_object_free_events = 1;
 599 
 600   if(!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
 601     return JNI_ERR;
 602   }
 603 
 604   memset(&event_callbacks, 0, sizeof(jvmtiEventCallbacks));
 605   event_callbacks.ObjectFree = &object_free_callback;
 606   if(!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&event_callbacks, sizeof(jvmtiEventCallbacks)))) {
 607     return JNI_ERR;
 608   }
 609 
 610   if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agent, NULL))) {
 611     return JNI_ERR;
 612   }
 613 
 614   return JNI_OK;
 615 }
 616 
 617 }