1 /*
2 * Copyright (c) 2003, 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 "jvmti.h"
26 #include "agent_common.h"
27 #include "jni_tools.h"
28 #include "jvmti_tools.h"
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /* ============================================================================= */
35
36 static jlong timeout = 0;
37
38 #define INFO_NONE 0x00
39 #define INFO_ALL 0xFF
40 #define INFO_OBJREF 0x01
41 #define INFO_STACKREF 0x02
42 #define INFO_HEAPROOT 0x04
43 #define INFO_HEAPOBJ 0x08
44 #define INFO_HEAPOBJ 0x08
45
46 static unsigned int info = INFO_NONE;
47
48 #define DEBUGEE_CLASS_NAME "nsk/jvmti/IterateOverInstancesOfClass/iterinstcls002"
49 #define ROOT_OBJECT_CLASS_NAME "nsk/jvmti/IterateOverInstancesOfClass/iterinstcls002RootTestedClass"
50 #define ROOT_OBJECT_CLASS_SIG "L"ROOT_OBJECT_CLASS_NAME";"
51 #define CHAIN_OBJECT_CLASS_NAME "nsk/jvmti/IterateOverInstancesOfClass/iterinstcls002TestedClass"
52 #define CHAIN_OBJECT_CLASS_SIG "L"CHAIN_OBJECT_CLASS_NAME";"
53
54 #define OBJECT_FIELD_NAME "object"
55 #define REACHABLE_CHAIN_FIELD_NAME "reachableChain"
56 #define UNREACHABLE_CHAIN_FIELD_NAME "unreachableChain"
57 #define TAIL_FIELD_NAME "tail"
58
59 #define DEFAULT_CHAIN_LENGTH 4
60
61 typedef struct ObjectDescStruct {
62 jlong tag;
63 jint found;
64 int collected;
65 } ObjectDesc;
66
67 static int chainLength = 0;
68 static int objectsCount = 0;
69
70 static ObjectDesc* objectDescList = NULL;
71
72 static volatile int foundUntagged = 0;
73
74 static int fakeUserData = 0;
75 static int userDataError = 0;
76
77 /* ============================================================================= */
78
79 /** Obtain chain of tested objects and tag them recursively. */
getChainObjects(jvmtiEnv * jvmti,JNIEnv * jni,jobject firstObject,jfieldID firstField,const char firstFieldName[],jfieldID nextField,const char nextFieldName[],int count,ObjectDesc objectDescList[],jlong tag,int reachable)80 static int getChainObjects(jvmtiEnv* jvmti, JNIEnv* jni, jobject firstObject,
81 jfieldID firstField, const char firstFieldName[],
82 jfieldID nextField, const char nextFieldName[],
83 int count, ObjectDesc objectDescList[],
84 jlong tag, int reachable) {
85
86 int success = NSK_TRUE;
87 jobject obj = NULL;
88 jlong objTag = (!reachable ? -tag : (tag % 2 != 0) ? tag : (jlong)0);
89
90 if (count <= 0)
91 return NSK_TRUE;
92
93 count--;
94 tag++;
95
96 if (!NSK_JNI_VERIFY(jni, (obj =
97 NSK_CPP_STUB3(GetObjectField, jni, firstObject, firstField)) != NULL)) {
98 nsk_jvmti_setFailStatus();
99 return NSK_FALSE;
100 }
101
102 objectDescList[count].tag = objTag;
103 if (!NSK_JVMTI_VERIFY(
104 NSK_CPP_STUB3(SetTag, jvmti, obj, objTag))) {
105 nsk_jvmti_setFailStatus();
106 return NSK_FALSE;
107 }
108 NSK_DISPLAY2(" tag=%-5ld object=0x%p\n", (long)objTag, (void*)obj);
109
110 if (!getChainObjects(jvmti, jni, obj, nextField, nextFieldName,
111 nextField, nextFieldName,
112 count, objectDescList, tag, reachable)) {
113 return NSK_FALSE;
114 }
115
116 NSK_TRACE(NSK_CPP_STUB2(DeleteLocalRef, jni, obj));
117 return success;
118 }
119
120 /** Obtain all tested objects from debugee class and tag them recursively. */
getTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int chainLength,int * objectsCount,ObjectDesc ** objectDescList,jclass * testedClass)121 static int getTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
122 int *objectsCount, ObjectDesc* *objectDescList,
123 jclass *testedClass) {
124 jclass debugeeClass = NULL;
125 jclass rootObjectClass = NULL;
126 jclass chainObjectClass = NULL;
127
128 jfieldID objectField = NULL;
129 jfieldID reachableChainField = NULL;
130 jfieldID unreachableChainField = NULL;
131 jfieldID tailField = NULL;
132
133 jobject rootObject = NULL;
134
135 jlong testedClassTag = 1;
136 jlong chainObjectTag = 100;
137
138 *objectsCount = 2 * chainLength;
139
140 NSK_DISPLAY1("Allocate memory for objects list: %d objects\n", *objectsCount);
141 if (!NSK_JVMTI_VERIFY(
142 NSK_CPP_STUB3(Allocate, jvmti, (*objectsCount * sizeof(ObjectDesc)),
143 (unsigned char**)objectDescList))) {
144 nsk_jvmti_setFailStatus();
145 return NSK_FALSE;
146 }
147 NSK_DISPLAY1(" ... allocated array: 0x%p\n", (void*)objectDescList);
148
149 {
150 int k;
151 for (k = 0; k < *objectsCount; k++) {
152 (*objectDescList)[k].tag = 0;
153 (*objectDescList)[k].found = 0;
154 (*objectDescList)[k].collected = 0;
155 }
156 }
157
158 NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);
159 if (!NSK_JNI_VERIFY(jni, (debugeeClass =
160 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) {
161 nsk_jvmti_setFailStatus();
162 return NSK_FALSE;
163 }
164 NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);
165
166 NSK_DISPLAY1("Find root object class: %s\n", ROOT_OBJECT_CLASS_NAME);
167 if (!NSK_JNI_VERIFY(jni, (rootObjectClass =
168 NSK_CPP_STUB2(FindClass, jni, ROOT_OBJECT_CLASS_NAME)) != NULL)) {
169 nsk_jvmti_setFailStatus();
170 return NSK_FALSE;
171 }
172 NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)rootObjectClass);
173
174 NSK_DISPLAY1("Find chain object class: %s\n", CHAIN_OBJECT_CLASS_NAME);
175 if (!NSK_JNI_VERIFY(jni, (chainObjectClass =
176 NSK_CPP_STUB2(FindClass, jni, CHAIN_OBJECT_CLASS_NAME)) != NULL)) {
177 nsk_jvmti_setFailStatus();
178 return NSK_FALSE;
179 }
180 NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)chainObjectClass);
181
182 NSK_DISPLAY1("Create global ref to tested class: 0x%p\n", chainObjectClass);
183 if (!NSK_JNI_VERIFY(jni, (*testedClass = (jclass)
184 NSK_CPP_STUB2(NewGlobalRef, jni, chainObjectClass)) != NULL)) {
185 nsk_jvmti_setFailStatus();
186 return NSK_FALSE;
187 }
188 NSK_DISPLAY1(" ... global ref: 0x%p\n", (void*)*testedClass);
189
190 NSK_DISPLAY1("Find static field in debugee class: %s\n", OBJECT_FIELD_NAME);
191 if (!NSK_JNI_VERIFY(jni, (objectField =
192 NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass,
193 OBJECT_FIELD_NAME, ROOT_OBJECT_CLASS_SIG)) != NULL)) {
194 nsk_jvmti_setFailStatus();
195 return NSK_FALSE;
196 }
197 NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)objectField);
198
199 NSK_DISPLAY1("Find instance field in root object class: %s\n", REACHABLE_CHAIN_FIELD_NAME);
200 if (!NSK_JNI_VERIFY(jni, (reachableChainField =
201 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass,
202 REACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
203 nsk_jvmti_setFailStatus();
204 return NSK_FALSE;
205 }
206 NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)reachableChainField);
207
208 NSK_DISPLAY1("Find instance field in root object class: %s\n", UNREACHABLE_CHAIN_FIELD_NAME);
209 if (!NSK_JNI_VERIFY(jni, (unreachableChainField =
210 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass,
211 UNREACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
212 nsk_jvmti_setFailStatus();
213 return NSK_FALSE;
214 }
215 NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)unreachableChainField);
216
217 NSK_DISPLAY1("Find instance field in chain object class: %s\n", TAIL_FIELD_NAME);
218 if (!NSK_JNI_VERIFY(jni, (tailField =
219 NSK_CPP_STUB4(GetFieldID, jni, chainObjectClass,
220 TAIL_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
221 nsk_jvmti_setFailStatus();
222 return NSK_FALSE;
223 }
224 NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)tailField);
225
226 NSK_DISPLAY1("Get root object from static field: %s\n", OBJECT_FIELD_NAME);
227 if (!NSK_JNI_VERIFY(jni, (rootObject =
228 NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass,
229 objectField)) != NULL)) {
230 nsk_jvmti_setFailStatus();
231 return NSK_FALSE;
232 }
233 NSK_DISPLAY1(" ... got object: 0x%p\n", (void*)rootObject);
234
235 NSK_DISPLAY0("Obtain and tag chain objects:\n");
236
237 NSK_DISPLAY0(" tested class object:\n");
238 if (!NSK_JVMTI_VERIFY(
239 NSK_CPP_STUB3(SetTag, jvmti, *testedClass, testedClassTag))) {
240 nsk_jvmti_setFailStatus();
241 return NSK_FALSE;
242 }
243 NSK_DISPLAY2(" tag=%-5ld object=0x%p\n", (long)testedClassTag, (void*)*testedClass);
244
245 NSK_DISPLAY1(" reachable objects chain: %d objects\n", chainLength);
246 if (!getChainObjects(jvmti, jni, rootObject,
247 reachableChainField, REACHABLE_CHAIN_FIELD_NAME,
248 tailField, TAIL_FIELD_NAME,
249 chainLength, *objectDescList,
250 chainObjectTag, NSK_TRUE)) {
251 nsk_jvmti_setFailStatus();
252 return NSK_FALSE;
253 }
254
255 NSK_DISPLAY1(" unreachable objects chain: %d objects\n", chainLength);
256 if (!getChainObjects(jvmti, jni, rootObject,
257 unreachableChainField, UNREACHABLE_CHAIN_FIELD_NAME,
258 tailField, TAIL_FIELD_NAME,
259 chainLength, *objectDescList + chainLength,
260 chainObjectTag, NSK_FALSE)) {
261 nsk_jvmti_setFailStatus();
262 return NSK_FALSE;
263 }
264
265 return NSK_TRUE;
266 }
267
268 /** Check if tagged objects were iterated. */
checkTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int chainLength,ObjectDesc objectDescList[])269 static int checkTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni,
270 int chainLength, ObjectDesc objectDescList[]) {
271 int success = NSK_TRUE;
272 int expectedUntagged = 0;
273 int i;
274
275 NSK_DISPLAY0("Following tagged/untagged objects were iterated:\n");
276
277 NSK_DISPLAY0(" reachable objects:\n");
278 for (i = 0; i < chainLength; i++) {
279 NSK_DISPLAY2(" tag=%-5ld iterated=%d times\n",
280 (long)objectDescList[i].tag, objectDescList[i].found);
281
282 if (objectDescList[i].found <= 0
283 && objectDescList[i].tag != 0) {
284 NSK_COMPLAIN2("Reachable tagged object was not iterated:\n"
285 "# tag: %ld\n"
286 "# iterated: %d times\n",
287 (long)objectDescList[i].tag,
288 objectDescList[i].found);
289 nsk_jvmti_setFailStatus();
290 }
291
292 if (objectDescList[i].tag == 0) {
293 expectedUntagged++;
294 }
295 }
296
297 NSK_DISPLAY0(" unreachable objects:\n");
298 for (i = 0; i < chainLength; i++) {
299 NSK_DISPLAY3(" tag=%-5ld iterated=%-3d collected=%d times\n",
300 (long)objectDescList[i + chainLength].tag,
301 objectDescList[i + chainLength].found,
302 objectDescList[i + chainLength].collected);
303
304 if (objectDescList[i + chainLength].found <= 0
305 && objectDescList[i + chainLength].collected <= 0) {
306 NSK_COMPLAIN2("Not collected unreachable tagged object was not iterated:\n"
307 "# tag: %ld\n"
308 "# iterated: %d times\n",
309 (long)objectDescList[i + chainLength].tag,
310 objectDescList[i + chainLength].found);
311 nsk_jvmti_setFailStatus();
312 }
313 }
314
315 NSK_DISPLAY0(" untagged objects:\n");
316 NSK_DISPLAY2(" total=%-3d iterated=%d objects\n",
317 expectedUntagged, foundUntagged);
318 if (foundUntagged > 0) {
319 NSK_COMPLAIN2("A number of untagged objects were iterated:\n"
320 "# iterated untagged objects: %d\n"
321 "# total untagged objects: %d\n",
322 foundUntagged, expectedUntagged);
323 nsk_jvmti_setFailStatus();
324 }
325
326 return NSK_TRUE;
327 }
328
329 /** Release references to the tested objects and free allocated memory. */
releaseTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int chainLength,ObjectDesc * objectDescList,jclass testedClass)330 static int releaseTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
331 ObjectDesc* objectDescList, jclass testedClass) {
332 if (testedClass != NULL) {
333 NSK_DISPLAY1("Release object reference to tested class: 0x%p\n", testedClass);
334 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, testedClass));
335 }
336
337 if (objectDescList != NULL) {
338 NSK_DISPLAY1("Deallocate objects list: 0x%p\n", (void*)objectDescList);
339 if (!NSK_JVMTI_VERIFY(
340 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)objectDescList))) {
341 nsk_jvmti_setFailStatus();
342 }
343 }
344
345 return NSK_TRUE;
346 }
347
348 /* ============================================================================= */
349
350 /** heapRootCallback for heap iterator. */
351 jvmtiIterationControl JNICALL
heapObjectCallback(jlong class_tag,jlong size,jlong * tag_ptr,void * user_data)352 heapObjectCallback(jlong class_tag, jlong size, jlong* tag_ptr, void* user_data) {
353
354 if (info & INFO_HEAPOBJ) {
355 NSK_DISPLAY3(" heapObjectCallback: class_tag=%-3ld size=%-3ld *tag_ptr=%-5ld\n",
356 (long)class_tag, (long)size,
357 (long)(tag_ptr == NULL ? (jlong)0 : *tag_ptr));
358 }
359
360 if (class_tag != 1) {
361 NSK_COMPLAIN3("Unexpected class_tag passed to heapObjectCallback:\n"
362 "# object tag: %ld\n"
363 "# class_tag: %ld\n"
364 "# size: %ld\n",
365 (long)*tag_ptr,
366 (long)class_tag,
367 (long)size);
368 nsk_jvmti_setFailStatus();
369 }
370
371 if (tag_ptr == NULL) {
372 NSK_COMPLAIN3("NULL tag_ptr is passed to heapObjectCallback:\n"
373 "# tag_ptr: 0x%p\n"
374 "# class_tag: %ld\n"
375 "# size: %ld\n",
376 (void*)tag_ptr,
377 (long)class_tag,
378 (long)size);
379 nsk_jvmti_setFailStatus();
380 } else {
381 if (*tag_ptr == 0) {
382 foundUntagged++;
383 NSK_COMPLAIN3("Untagged object passed to heapObjectCallback:\n"
384 "# tag: %ld\n"
385 "# class_tag: %ld\n"
386 "# size: %ld\n",
387 (long)*tag_ptr,
388 (long)class_tag,
389 (long)size);
390 nsk_jvmti_setFailStatus();
391 } else {
392 int found = 0;
393 int i;
394
395 for (i = 0; i < objectsCount; i++) {
396 if (*tag_ptr == objectDescList[i].tag) {
397 found++;
398 objectDescList[i].found++;
399 break;
400 }
401 }
402
403 if (found <= 0) {
404 NSK_COMPLAIN3("Unknown tagged object passed to heapObjectCallback:\n"
405 "# tag: %ld\n"
406 "# class_tag: %ld\n"
407 "# size: %ld\n",
408 (long)*tag_ptr,
409 (long)class_tag,
410 (long)size);
411 nsk_jvmti_setFailStatus();
412 }
413 }
414 }
415
416 if (user_data != &fakeUserData && !userDataError) {
417 NSK_COMPLAIN2("Unexpected user_data is passed to heapObjectCallback:\n"
418 "# expected: 0x%p\n"
419 "# actual: 0x%p\n",
420 user_data,
421 &fakeUserData);
422 nsk_jvmti_setFailStatus();
423 userDataError++;
424 }
425
426 return JVMTI_ITERATION_CONTINUE;
427 }
428
429 /* ============================================================================= */
430
431 /** Agent algorithm. */
432 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * jni,void * arg)433 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
434 NSK_DISPLAY0("Wait for tested objects created\n");
435 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
436 return;
437
438 {
439 jclass testedClass = NULL;
440
441 NSK_DISPLAY0(">>> Obtain and tag tested objects from debugee class\n");
442 {
443 if (!NSK_VERIFY(getTestedObjects(jvmti, jni, chainLength,
444 &objectsCount, &objectDescList, &testedClass)))
445 return;
446 }
447
448 NSK_DISPLAY0(">>> Enable OBJECT_FREE event and let debugee to clean links to unreachable objects\n");
449 {
450 jvmtiEvent event = JVMTI_EVENT_OBJECT_FREE;
451 if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_ENABLE, 1, &event, NULL)))
452 return;
453
454 if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
455 return;
456 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
457 return;
458 }
459
460 NSK_DISPLAY0(">>> Iterate over instances of tested class with filter JVMTI_HEAP_OBJECT_TAGGED\n");
461 {
462 if (!NSK_JVMTI_VERIFY(
463 NSK_CPP_STUB5(IterateOverInstancesOfClass, jvmti,
464 testedClass, JVMTI_HEAP_OBJECT_TAGGED,
465 heapObjectCallback, &fakeUserData))) {
466 nsk_jvmti_setFailStatus();
467 return;
468 }
469 }
470
471 NSK_DISPLAY0(">>> Disable OBJECT_FREE event and check if tagged objects were iterated:\n");
472 {
473 jvmtiEvent event = JVMTI_EVENT_OBJECT_FREE;
474 if (!NSK_VERIFY(nsk_jvmti_enableEvents(JVMTI_DISABLE, 1, &event, NULL)))
475 return;
476
477 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
478 nsk_jvmti_setFailStatus();
479 }
480 }
481
482 NSK_DISPLAY0(">>> Clean used data\n");
483 {
484 if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, chainLength,
485 objectDescList, testedClass)))
486 return;
487 }
488 }
489
490 NSK_DISPLAY0("Let debugee to finish\n");
491 if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
492 return;
493 }
494
495 /* ============================================================================= */
496
497 JNIEXPORT void JNICALL
callbackObjectFree(jvmtiEnv * jvmti,jlong tag)498 callbackObjectFree(jvmtiEnv* jvmti, jlong tag) {
499 int i;
500
501 if (info & INFO_HEAPOBJ) {
502 NSK_DISPLAY1(" <ObjectFree>: tag=%-5ld\n", tag);
503 }
504
505 if (tag != 0) {
506 for (i = 0; i < objectsCount; i++) {
507 if (tag == objectDescList[i].tag) {
508 objectDescList[i].collected++;
509 break;
510 }
511 }
512 }
513 }
514
515 /* ============================================================================= */
516
517 /** Agent library initialization. */
518 #ifdef STATIC_BUILD
Agent_OnLoad_iterinstcls002(JavaVM * jvm,char * options,void * reserved)519 JNIEXPORT jint JNICALL Agent_OnLoad_iterinstcls002(JavaVM *jvm, char *options, void *reserved) {
520 return Agent_Initialize(jvm, options, reserved);
521 }
Agent_OnAttach_iterinstcls002(JavaVM * jvm,char * options,void * reserved)522 JNIEXPORT jint JNICALL Agent_OnAttach_iterinstcls002(JavaVM *jvm, char *options, void *reserved) {
523 return Agent_Initialize(jvm, options, reserved);
524 }
JNI_OnLoad_iterinstcls002(JavaVM * jvm,char * options,void * reserved)525 JNIEXPORT jint JNI_OnLoad_iterinstcls002(JavaVM *jvm, char *options, void *reserved) {
526 return JNI_VERSION_1_8;
527 }
528 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)529 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
530 jvmtiEnv* jvmti = NULL;
531
532 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
533 return JNI_ERR;
534
535 timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
536
537 {
538 const char* infoOpt = nsk_jvmti_findOptionValue("info");
539 if (infoOpt != NULL) {
540 if (strcmp(infoOpt, "none") == 0)
541 info = INFO_NONE;
542 else if (strcmp(infoOpt, "all") == 0)
543 info = INFO_ALL;
544 else if (strcmp(infoOpt, "objref") == 0)
545 info = INFO_OBJREF;
546 else if (strcmp(infoOpt, "stackref") == 0)
547 info = INFO_STACKREF;
548 else if (strcmp(infoOpt, "heaproot") == 0)
549 info = INFO_HEAPROOT;
550 else if (strcmp(infoOpt, "heapobj") == 0)
551 info = INFO_HEAPOBJ;
552 else {
553 NSK_COMPLAIN1("Unknown option value: info=%s\n", infoOpt);
554 return JNI_ERR;
555 }
556 }
557 }
558
559 chainLength = nsk_jvmti_findOptionIntValue("objects", DEFAULT_CHAIN_LENGTH);
560 if (!NSK_VERIFY(chainLength > 0))
561 return JNI_ERR;
562
563 if (!NSK_VERIFY((jvmti =
564 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
565 return JNI_ERR;
566
567 {
568 jvmtiCapabilities caps;
569
570 memset(&caps, 0, sizeof(caps));
571 caps.can_tag_objects = 1;
572 caps.can_generate_object_free_events = 1;
573 if (!NSK_JVMTI_VERIFY(
574 NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) {
575 return JNI_ERR;
576 }
577 }
578
579 {
580 jvmtiEventCallbacks eventCallbacks;
581 memset(&eventCallbacks, 0, sizeof(eventCallbacks));
582 eventCallbacks.ObjectFree = callbackObjectFree;
583 if (!NSK_JVMTI_VERIFY(
584 NSK_CPP_STUB3(SetEventCallbacks, jvmti,
585 &eventCallbacks, sizeof(eventCallbacks))))
586 return JNI_ERR;
587 }
588
589 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
590 return JNI_ERR;
591
592 return JNI_OK;
593 }
594
595 /* ============================================================================= */
596
597 #ifdef __cplusplus
598 }
599 #endif
600