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 /*
  37   For this test tags have following format:
  38   |63       48|      32|     16|      0|
  39   |<not used> |tag type|obj idx|fld idx|
  40 */
  41 
  42 #define FIELD_TAG 1
  43 #define OBJECT_TAG 2
  44 #define CLASS_TAG 4
  45 
  46 #define ENCODE_TAG(type, obj, fld) (((jlong)type)<<32 | ((jlong)obj)<<16 | (jlong)fld)
  47 #define DECODE_TYPE(tag) tag>>32
  48 #define DECODE_OBJECT(tag) ((tag>>16)&0xFFFF)
  49 #define DECODE_FIELD(tag) (tag&0xFFFF)
  50 
  51 #define TEST_OBJECTS_COUNT 2
  52 #define TAGGED_OBJECTS 1
  53 
  54 static long timeout = 0;
  55 static int filter_type = -1;
  56 
  57 // by default at least one object will be reported regardless to filter type
  58 static int expected_object_count = 1;
  59 static int reported_objects = 0;
  60 
  61 //expected values
  62 #define INT_ARRAY_LENGTH 2
  63 
  64 static jint TAGGED_STATIC_INT_VALUE = 0xC0DE01;
  65 static jint TAGGED_INT_VALUE = 0xC0DE02;
  66 static jint UNTAGGED_STATIC_INT_VALUE = 0xC0DE03;
  67 static jint UNTAGGED_INT_VALUE = 0xC0DE04;
  68 static jint TAGGED_INT_ARRAY_VALUE[] = {0xC0DE01,
  69                                                  0xC0DE01+1};
  70 static jint UNTAGGED_INT_ARRAY_VALUE[] = {0xC0DE03,
  71                                                    0xC0DE03+1};
  72 static const wchar_t *TAGGED_STRING_VALUE = L"I'm a tagged string";
  73 static const wchar_t *UNTAGGED_STRING_VALUE = L"I'm an untagged string";
  74 
  75 //kind of field
  76 #define TYPE_FIELD 1
  77 #define TYPE_ARRAY 2
  78 #define TYPE_STRING 4
  79 
  80 //field info
  81 typedef struct {
  82   char *name;
  83   char *signature;
  84   int found;
  85   int collected;
  86   int primitive;
  87   int expected;
  88   int type;
  89   void *value;
  90   int size;
  91 } field_info_t;
  92 
  93 //object info
  94 typedef struct {
  95   char *name;
  96   jint fields_count;
  97   field_info_t *fields;
  98   int collected;
  99 } object_info_t;
 100 
 101 static object_info_t objects_info[TEST_OBJECTS_COUNT];
 102 
 103 #define className "nsk/jvmti/IterateThroughHeap/filter_tagged/HeapFilter"
 104 #define fieldName "testObjects"
 105 #define fieldSig "[Ljava/lang/Object;"
 106 #define STRING_SIGNATURE "Ljava/lang/String;"
 107 #define INT_ARRAY_SIGNATURE "[I"
 108 
 109 // Check if the signature is signature of primitive type.
 110 jboolean is_primitive_type(const char *signature) {
 111   if (!strcmp(signature,"C")
 112       || !strcmp(signature, "B")
 113       || !strcmp(signature, "S")
 114       || !strcmp(signature, "I")
 115       || !strcmp(signature, "J")
 116       || !strcmp(signature, "F")
 117       || !strcmp(signature, "D")
 118       || !strcmp(signature, "Z"))
 119     return JNI_TRUE;
 120   return JNI_FALSE;
 121 }
 122 
 123 //check tag values accoring to heap filter choosed for test
 124 jboolean verify_tag(jlong class_tag, jlong object_tag) {
 125   switch (filter_type) {
 126   case JVMTI_HEAP_FILTER_TAGGED:
 127     return object_tag == 0;
 128   case JVMTI_HEAP_FILTER_UNTAGGED:
 129     return object_tag != 0;
 130   case JVMTI_HEAP_FILTER_CLASS_TAGGED:
 131     return class_tag == 0;
 132   case JVMTI_HEAP_FILTER_CLASS_UNTAGGED:
 133     return class_tag != 0;
 134   default:
 135     return JNI_FALSE;
 136   }
 137 }
 138 
 139 //check whether or not field expected to be reported
 140 jboolean occurance_expected(int tagged, int is_static, int is_primitive) {
 141   switch (filter_type) {
 142   case JVMTI_HEAP_FILTER_TAGGED:
 143     return !tagged;
 144   case JVMTI_HEAP_FILTER_UNTAGGED:
 145     return tagged;
 146   case JVMTI_HEAP_FILTER_CLASS_TAGGED:
 147     return (is_static && is_primitive) || !is_primitive || !tagged;
 148   case JVMTI_HEAP_FILTER_CLASS_UNTAGGED:
 149     return !is_static && is_primitive && tagged;
 150   default:
 151     return JNI_ERR;
 152   }
 153 }
 154 
 155 jint JNICALL field_callback(jvmtiHeapReferenceKind kind,
 156                             const jvmtiHeapReferenceInfo* info,
 157                             jlong object_class_tag,
 158                             jlong* object_tag_ptr,
 159                             jvalue value,
 160                             jvmtiPrimitiveType value_type,
 161                             void* user_data) {
 162   int object;
 163   int field;
 164   if (!NSK_VERIFY(verify_tag(object_class_tag, *object_tag_ptr))) {
 165     nsk_jvmti_setFailStatus();
 166   }
 167 
 168   //iterate over all fields found during tagging and compare reported value
 169   //with their values.
 170   if (value_type != JVMTI_PRIMITIVE_TYPE_INT)
 171     return 0;
 172   for (object = 0; object < TEST_OBJECTS_COUNT; object++) {
 173     for (field = 0; field < objects_info[object].fields_count; field++) {
 174       if (objects_info[object].fields[field].type == TYPE_FIELD &&
 175          *(jint*)(objects_info[object].fields[field].value) == value.i) {
 176         objects_info[object].fields[field].found++;
 177       }
 178     }
 179   }
 180   return 0;
 181 }
 182 
 183 jint JNICALL string_callback(jlong class_tag,
 184                              jlong size,
 185                              jlong* tag_ptr,
 186                              const jchar* value,
 187                              jint value_length,
 188                              void* user_data) {
 189   int object;
 190   int field;
 191   if (!NSK_VERIFY(verify_tag(class_tag, *tag_ptr))) {
 192     nsk_jvmti_setFailStatus();
 193   }
 194   for (object = 0; object < TEST_OBJECTS_COUNT; object++) {
 195     for (field = 0; field < objects_info[object].fields_count; field++) {
 196       if (objects_info[object].fields[field].type == TYPE_STRING &&
 197          value_length == objects_info[object].fields[field].size) {
 198         int matched = 1;
 199         int i;
 200         wchar_t *str = (wchar_t*)objects_info[object].fields[field].value;
 201         for (i = 0; i < value_length && matched; i++) {
 202           matched = (str[i] == value[i]);
 203         }
 204         if (matched)
 205           objects_info[object].fields[field].found++;
 206       }
 207     }
 208   }
 209   return 0;
 210 }
 211 
 212 
 213 jint JNICALL array_callback(jlong class_tag,
 214                             jlong size,
 215                             jlong* tag_ptr,
 216                             jint element_count,
 217                             jvmtiPrimitiveType element_type,
 218                             const void* elements,
 219                             void* user_data) {
 220   int object;
 221   int field;
 222   if (!NSK_VERIFY(verify_tag(class_tag, *tag_ptr))) {
 223     nsk_jvmti_setFailStatus();
 224   }
 225   for (object = 0; object < TEST_OBJECTS_COUNT; object++) {
 226     for (field = 0; field < objects_info[object].fields_count; field++) {
 227       if (objects_info[object].fields[field].type == TYPE_ARRAY &&
 228          element_count == objects_info[object].fields[field].size) {
 229         int matched = 1;
 230         int i;
 231         for (i = 0; i < element_count && matched; i++) {
 232           matched = ((jint*)objects_info[object].fields[field].value)[i]==
 233             ((jint*)elements)[i];
 234         }
 235         if (matched)
 236           objects_info[object].fields[field].found++;
 237       }
 238     }
 239   }
 240   return 0;
 241 }
 242 
 243 jint JNICALL heap_callback(jlong class_tag,
 244                            jlong size,
 245                            jlong* tag_ptr,
 246                            jint length,
 247                            void* user_data) {
 248   if (!NSK_VERIFY(verify_tag(class_tag, *tag_ptr))) {
 249     NSK_COMPLAIN0("Tag values invalid for selected heap filter were passed "
 250                   "to jvmtiHeapIterationCallback.\n");
 251     NSK_COMPLAIN2("\tClass tag: 0x%lX;\n\tObject tag: 0x%lX.\n", class_tag, *tag_ptr);
 252     nsk_jvmti_setFailStatus();
 253   }
 254   reported_objects++;
 255   return 0;
 256 }
 257 
 258 JNIEXPORT void JNICALL
 259 object_free_callback(jvmtiEnv* jvmti, jlong tag) {
 260   if (DECODE_TYPE(tag) == OBJECT_TAG) {
 261     objects_info[DECODE_OBJECT(tag)].collected = 1;
 262   } else if (DECODE_TYPE(tag) == FIELD_TAG) {
 263     objects_info[DECODE_OBJECT(tag)].fields[DECODE_FIELD(tag)].collected = 1;
 264   }
 265 }
 266 
 267 //set expected fields value according to it's type
 268 void set_expected_value(field_info_t *field, int tagged, int is_static) {
 269   if (field->primitive) {
 270     field->size = (int) sizeof(jint);
 271     if (is_static) {
 272       field->value = (void*)(tagged ? &TAGGED_STATIC_INT_VALUE:
 273                              &UNTAGGED_STATIC_INT_VALUE);
 274     } else {
 275       field->value = (void*)(tagged ? &TAGGED_INT_VALUE:
 276                              &UNTAGGED_INT_VALUE);
 277     }
 278     field->type = TYPE_FIELD;
 279   } else if (0==strcmp(field->signature,STRING_SIGNATURE)) {
 280     field->value = (void*)(tagged ? TAGGED_STRING_VALUE:
 281                            UNTAGGED_STRING_VALUE);
 282     field->size = (int) wcslen((wchar_t*)field->value);
 283     field->type = TYPE_STRING;
 284   } else if (0==strcmp(field->signature,INT_ARRAY_SIGNATURE)) {
 285     field->size = INT_ARRAY_LENGTH;
 286     field->value = (void*)(tagged ? TAGGED_INT_ARRAY_VALUE:
 287                            UNTAGGED_INT_ARRAY_VALUE);
 288     field->type = TYPE_ARRAY;
 289   }
 290 }
 291 
 292 /**
 293  * Read array of test objects.
 294  * Tag each of these objects, their classes, non-primitive fields and non-primitive fields classes.
 295  */
 296 int tag_objects(jvmtiEnv *jvmti, JNIEnv *jni) {
 297   jclass debugee;
 298   jfieldID testObjectsField;
 299   jobjectArray testObjects;
 300   int object;
 301 
 302   if (!NSK_VERIFY(NULL != (debugee = jni->FindClass(className))))
 303     return JNI_ERR;
 304 
 305   if (!NSK_VERIFY(NULL != (testObjectsField = jni->GetStaticFieldID(debugee, fieldName, fieldSig))))
 306     return JNI_ERR;
 307 
 308   if (!NSK_VERIFY(NULL != (testObjects = (jobjectArray)(jni->GetStaticObjectField(
 309           debugee, testObjectsField)))))
 310     return JNI_ERR;
 311 
 312   // For each of test objects tag every field
 313   for (object = 0; object<TEST_OBJECTS_COUNT; object++) {
 314     jobject target;
 315     jclass targetClass;
 316     jfieldID *targetFields;
 317     jint field;
 318     int tagged = object == 0;
 319 
 320     memset(&objects_info[object],0,sizeof(object_info_t));
 321     if (!NSK_VERIFY(NULL != (target = jni->GetObjectArrayElement(testObjects, object))))
 322       return JNI_ERR;
 323 
 324     if (!NSK_VERIFY(NULL != (targetClass = jni->GetObjectClass(target))))
 325       return JNI_ERR;
 326 
 327     if (!NSK_JVMTI_VERIFY(jvmti->GetClassSignature(targetClass, &(objects_info[object].name), NULL)))
 328       return JNI_ERR;
 329 
 330     if (!NSK_JVMTI_VERIFY(jvmti->GetClassFields(
 331             targetClass, &(objects_info[object].fields_count), &targetFields)))
 332       return JNI_ERR;
 333 
 334     objects_info[object].fields = (field_info_t*)calloc(objects_info[object].fields_count,sizeof(field_info_t));
 335 
 336     // Iterate over fields, collect info about it and tag non primitive fields.
 337     for (field = 0; field < objects_info[object].fields_count; field++) {
 338       jint modifiers;
 339       int is_static = 0;
 340       int is_primitive = 0;
 341       if (!NSK_JVMTI_VERIFY(jvmti->GetFieldName(targetClass,
 342                                                 targetFields[field],
 343                                                 &objects_info[object].fields[field].name,
 344                                                 &objects_info[object].fields[field].signature,
 345                                                 NULL)))
 346         return JNI_ERR;
 347       if (!NSK_JVMTI_VERIFY(jvmti->GetFieldModifiers(
 348               targetClass, targetFields[field], &modifiers))) {
 349         return JNI_ERR;
 350       }
 351       is_static = (modifiers & STATIC_FIELD) == STATIC_FIELD;
 352       if (is_primitive_type(objects_info[object].fields[field].signature)) {
 353         objects_info[object].fields[field].primitive = 1;
 354         is_primitive = 1;
 355       } else {
 356         jobject value;
 357         if (!NSK_JVMTI_VERIFY(jvmti->GetFieldModifiers(
 358                 targetClass, targetFields[field], &modifiers))) {
 359           return JNI_ERR;
 360         }
 361         if (is_static) {
 362           if (!NSK_VERIFY(NULL != (value = jni->GetStaticObjectField(
 363                   targetClass, targetFields[field])))) {
 364             return JNI_ERR;
 365           }
 366         } else {
 367           if (!NSK_VERIFY(NULL != (value = jni->GetObjectField(target, targetFields[field])))) {
 368             return JNI_ERR;
 369           }
 370         }
 371         if (tagged) {
 372           if (!NSK_JVMTI_VERIFY(jvmti->SetTag(value, ENCODE_TAG(FIELD_TAG,object,field)))) {
 373             return JNI_ERR;
 374           }
 375         }
 376         jni->DeleteLocalRef(value);
 377       }
 378 
 379       objects_info[object].fields[field].expected =
 380         occurance_expected(tagged,is_static,is_primitive);
 381       expected_object_count +=
 382         objects_info[object].fields[field].expected && !is_primitive;
 383       set_expected_value(&objects_info[object].fields[field], tagged, is_static);
 384     }
 385 
 386     // tag class and it's instance to pass this tag into primitive field callback
 387     if (tagged) {
 388       if (!NSK_JVMTI_VERIFY(jvmti->SetTag(target, ENCODE_TAG(OBJECT_TAG,object,0))))
 389         return JNI_ERR;
 390       if (!NSK_JVMTI_VERIFY(jvmti->SetTag(targetClass, ENCODE_TAG(CLASS_TAG,object,0))))
 391         return JNI_ERR;
 392     }
 393 
 394     NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)targetFields));
 395     jni->DeleteLocalRef(target);
 396     jni->DeleteLocalRef(targetClass);
 397   }
 398 
 399   jni->DeleteLocalRef(testObjects);
 400 
 401   return JNI_OK;
 402 }
 403 
 404 
 405 //release resources allocated in tag_objects
 406 void release_object_info(jvmtiEnv *jvmti, JNIEnv *jni) {
 407   int object;
 408   int field;
 409   for (object = 0; object < TEST_OBJECTS_COUNT; object++) {
 410     for (field = 0; field < objects_info[object].fields_count; field++) {
 411       jvmti->Deallocate((unsigned char*)objects_info[object].fields[field].name);
 412       jvmti->Deallocate((unsigned char*)objects_info[object].fields[field].signature);
 413     }
 414     jvmti->Deallocate((unsigned char*)objects_info[object].name);
 415     free(objects_info[object].fields);
 416   }
 417 }
 418 
 419 // Check that every field was found expected amount of times
 420 void verify_objects(int reachable) {
 421   int object;
 422   int field;
 423   for (object = 0; object < (reachable?TEST_OBJECTS_COUNT:TAGGED_OBJECTS); object++) {
 424     for (field = 0; field < objects_info[object].fields_count; field++) {
 425       // If primitive field of object that was not collected or
 426       // non primitive field that was not collected was not found
 427       // expected amount of times, than test failed.
 428       if ((objects_info[object].fields[field].primitive &&
 429            !objects_info[object].collected)
 430           ||
 431           (!objects_info[object].fields[field].primitive &&
 432            !objects_info[object].fields[field].collected)) {
 433         if (objects_info[object].fields[field].expected !=
 434             objects_info[object].fields[field].found) {
 435           NSK_COMPLAIN4("Field %s::%s expected to be found %d times, "
 436                         "but it was found %d times.\n",
 437                         objects_info[object].name,
 438                         objects_info[object].fields[field].name,
 439                         objects_info[object].fields[field].expected,
 440                         objects_info[object].fields[field].found);
 441           nsk_jvmti_setFailStatus();
 442         }
 443       }
 444       objects_info[object].fields[field].found = 0;
 445     }
 446   }
 447 }
 448 
 449 static void JNICALL
 450 agent(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
 451   jvmtiEvent event = JVMTI_EVENT_OBJECT_FREE;
 452   jvmtiHeapCallbacks primitive_callbacks;
 453   jvmtiEventCallbacks event_callbacks;
 454 
 455   NSK_DISPLAY0("Waiting debugee.\n");
 456   if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL))) {
 457     return;
 458   }
 459   if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
 460     return;
 461   }
 462 
 463   NSK_DISPLAY0("Tagging fields.\n");
 464   if (!NSK_VERIFY(JNI_OK==tag_objects(jvmti, jni))) {
 465     return;
 466   }
 467 
 468   memset(&primitive_callbacks, 0, sizeof(jvmtiHeapCallbacks));
 469   primitive_callbacks.primitive_field_callback = &field_callback;
 470   primitive_callbacks.array_primitive_value_callback = &array_callback;
 471   primitive_callbacks.string_primitive_value_callback = &string_callback;
 472   primitive_callbacks.heap_iteration_callback = &heap_callback;
 473 
 474   NSK_DISPLAY0("Iterating over reachable objects.\n");
 475   if (!NSK_JVMTI_VERIFY(jvmti->IterateThroughHeap(filter_type, NULL, &primitive_callbacks, NULL))) {
 476     nsk_jvmti_setFailStatus();
 477     return;
 478   }
 479 
 480   NSK_DISPLAY0("Verifying that all fields were found.\n");
 481   verify_objects(1);
 482 
 483   if (!NSK_VERIFY(nsk_jvmti_resumeSync())) {
 484     return;
 485   }
 486 
 487   if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
 488     return;
 489   }
 490 
 491   NSK_DISPLAY0("Iterating over unreachable objects.\n");
 492   if (!NSK_JVMTI_VERIFY(jvmti->IterateThroughHeap(filter_type, NULL, &primitive_callbacks, NULL))) {
 493     nsk_jvmti_setFailStatus();
 494     return;
 495   }
 496 
 497   NSK_DISPLAY0("Verifying that all fields were found.\n");
 498   verify_objects(0);
 499 
 500   /*
 501    * This is done to clear event_callbacks.ObjectFree before we call release_object_info(),
 502    * since it will free some memory that the callback will access.
 503    */
 504   memset(&event_callbacks, 0, sizeof(jvmtiEventCallbacks));
 505   if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&event_callbacks, sizeof(jvmtiEventCallbacks)))) {
 506     return;
 507   }
 508 
 509   release_object_info(jvmti, jni);
 510 
 511   if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
 512     return;
 513 }
 514 
 515 #ifdef STATIC_BUILD
 516 JNIEXPORT jint JNICALL Agent_OnLoad_HeapFilter(JavaVM *jvm, char *options, void *reserved) {
 517     return Agent_Initialize(jvm, options, reserved);
 518 }
 519 JNIEXPORT jint JNICALL Agent_OnAttach_HeapFilter(JavaVM *jvm, char *options, void *reserved) {
 520     return Agent_Initialize(jvm, options, reserved);
 521 }
 522 JNIEXPORT jint JNI_OnLoad_HeapFilter(JavaVM *jvm, char *options, void *reserved) {
 523     return JNI_VERSION_1_8;
 524 }
 525 #endif
 526 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 527   jvmtiEnv *jvmti;
 528   jvmtiCapabilities caps;
 529   jvmtiEventCallbacks event_callbacks;
 530   const char *type;
 531 
 532   jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved);
 533   if (!NSK_VERIFY(jvmti != NULL)) {
 534     return JNI_ERR;
 535   }
 536 
 537   nsk_jvmti_parseOptions(options);
 538 
 539   type = nsk_jvmti_findOptionValue("filter");
 540   if (type != NULL) {
 541     if (0 == strcmp(type, "JVMTI_HEAP_FILTER_TAGGED")) {
 542       filter_type = JVMTI_HEAP_FILTER_TAGGED;
 543     } else if (0 == strcmp(type, "JVMTI_HEAP_FILTER_UNTAGGED")) {
 544       filter_type = JVMTI_HEAP_FILTER_UNTAGGED;
 545     } else if (0 == strcmp(type, "JVMTI_HEAP_FILTER_CLASS_TAGGED")) {
 546       filter_type = JVMTI_HEAP_FILTER_CLASS_TAGGED;
 547     } else if (0 == strcmp(type, "JVMTI_HEAP_FILTER_CLASS_UNTAGGED")) {
 548       filter_type = JVMTI_HEAP_FILTER_CLASS_UNTAGGED;
 549     } else {
 550       NSK_COMPLAIN1("unknown filter value '%s'.\n",type);
 551       return JNI_ERR;
 552     }
 553   } else {
 554     NSK_COMPLAIN0("filter option shound be presented.\n");
 555     return JNI_ERR;
 556   }
 557 
 558   timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
 559 
 560   memset(&caps, 0, sizeof(caps));
 561   caps.can_tag_objects = 1;
 562   caps.can_generate_object_free_events = 1;
 563 
 564   if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
 565     return JNI_ERR;
 566   }
 567 
 568   memset(&event_callbacks, 0, sizeof(jvmtiEventCallbacks));
 569   event_callbacks.ObjectFree = &object_free_callback;
 570   if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&event_callbacks, sizeof(jvmtiEventCallbacks)))) {
 571     return JNI_ERR;
 572   }
 573 
 574   if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agent, NULL))) {
 575     return JNI_ERR;
 576   }
 577 
 578   return JNI_OK;
 579 }
 580 
 581 }