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