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 }