125 default:
126 // TODO: check that realy should be done w/ other jvmtiHeapReferenceKind
127 break;
128 }
129
130 return referrer_index;
131 } /* get_reference_index */
132
133
134 /** Initialize objectDescList. */
135 static int initObjectDescList(jvmtiEnv* jvmti,
136 int chainLength,
137 int* objectsCount,
138 ObjectDesc** objectDescList)
139 {
140 /* root object + reachable and unreachable object chains */
141 *objectsCount = 1 + 2 * chainLength;
142
143 printf("Allocate memory for objects list: %d objects\n", *objectsCount);
144 fflush(0);
145 if (!NSK_JVMTI_VERIFY(
146 NSK_CPP_STUB3(Allocate, jvmti,
147 (*objectsCount * sizeof(ObjectDesc)),
148 (unsigned char**) objectDescList))) {
149 nsk_jvmti_setFailStatus();
150 return NSK_FALSE;
151 }
152 printf(" ... allocated array: 0x%p\n", (void*)objectDescList);
153 fflush(0);
154
155 {
156 int k;
157 for (k = 0; k < *objectsCount; k++) {
158 (*objectDescList)[k].tag = 0;
159 (*objectDescList)[k].exp_class_tag = CHAIN_CLASS_TAG;
160 (*objectDescList)[k].exp_found = 0;
161 (*objectDescList)[k].found = 0;
162 }
163 }
164 (*objectDescList)[0].exp_class_tag = ROOT_CLASS_TAG;
165 (*objectDescList)[0].tag = ROOT_OBJECT_TAG;
166
167 /* Object with tag=100 must be referenced 2 times */
168 (*objectDescList)[chainLength].exp_found = 1;
169
170
171 return NSK_TRUE;
172 } /* initObjectDescList */
173
174
175 /** Find and tag classes. */
176 static int getAndTagClasses(jvmtiEnv* jvmti,
177 JNIEnv* jni,
178 jclass* debugeeClass,
179 jclass* rootObjectClass,
180 jclass* chainObjectClass)
181 {
182
183 if (!NSK_JNI_VERIFY(jni, (*debugeeClass =
184 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) {
185 nsk_jvmti_setFailStatus();
186 return NSK_FALSE;
187 }
188 printf("\nFound debugee class: 0x%p\n %s\n",
189 (void*) *debugeeClass, DEBUGEE_CLASS_NAME);
190 fflush(0);
191
192 if (!NSK_JNI_VERIFY(jni, (*rootObjectClass =
193 NSK_CPP_STUB2(FindClass, jni, ROOT_OBJECT_CLASS_NAME)) != NULL)) {
194 nsk_jvmti_setFailStatus();
195 return NSK_FALSE;
196 }
197
198 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti,
199 *rootObjectClass,
200 ROOT_CLASS_TAG))) {
201 nsk_jvmti_setFailStatus();
202 }
203
204 printf("\nFound root object class: 0x%p, tag=%ld\n %s\n",
205 (void*) *rootObjectClass,(long) ROOT_CLASS_TAG,
206 ROOT_OBJECT_CLASS_NAME);
207 fflush(0);
208
209
210 if (!NSK_JNI_VERIFY(jni, (*chainObjectClass =
211 NSK_CPP_STUB2(FindClass, jni, CHAIN_OBJECT_CLASS_NAME)) != NULL)) {
212 nsk_jvmti_setFailStatus();
213 return NSK_FALSE;
214 }
215
216 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti,
217 *chainObjectClass,
218 CHAIN_CLASS_TAG))) {
219 nsk_jvmti_setFailStatus();
220 }
221 printf("\nFound chain object class: 0x%p, tag=%ld\n %s\n",
222 (void*) *chainObjectClass, (long) CHAIN_CLASS_TAG,
223 CHAIN_OBJECT_CLASS_NAME);
224 fflush(0);
225
226 return NSK_TRUE;
227 } /* getAndTagClasses */
228
229
230 /** Obtain chain of tested objects and tag them recursively. */
231 static int getFieldsAndObjects(jvmtiEnv* jvmti,
232 JNIEnv* jni,
233 jclass debugeeClass,
234 jclass rootObjectClass,
235 jclass chainObjectClass,
236 jobject* rootObjectPtr,
237 jfieldID* reachableChainField,
238 jfieldID* unreachableChainField,
239 jfieldID* nextField)
240 {
241 jfieldID rootObjectField = NULL;
242
243 if (!NSK_JNI_VERIFY(jni, (rootObjectField =
244 NSK_CPP_STUB4(GetStaticFieldID, jni,
245 debugeeClass,
246 OBJECT_FIELD_NAME,
247 ROOT_OBJECT_CLASS_SIG)) != NULL)) {
248 nsk_jvmti_setFailStatus();
249 return NSK_FALSE;
250 }
251 printf("\nFound fieldID: 0x%p - \'%s\' static field in debugee class\n",
252 (void*) rootObjectField, OBJECT_FIELD_NAME);
253 fflush(0);
254
255 if (!NSK_JNI_VERIFY(jni, (*reachableChainField =
256 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass,
257 REACHABLE_CHAIN_FIELD_NAME,
258 CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
259 nsk_jvmti_setFailStatus();
260 return NSK_FALSE;
261 }
262 printf("\nFound fieldID: 0x%p - \'%s\' field in root object class\n",
263 (void*) reachableChainField, REACHABLE_CHAIN_FIELD_NAME);
264 fflush(0);
265
266 if (!NSK_JNI_VERIFY(jni, (*unreachableChainField =
267 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass,
268 UNREACHABLE_CHAIN_FIELD_NAME,
269 CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
270 nsk_jvmti_setFailStatus();
271 return NSK_FALSE;
272 }
273
274 printf("\nFound fieldID: 0x%p - \'%s\' field in root object class\n",
275 (void*) unreachableChainField, UNREACHABLE_CHAIN_FIELD_NAME);
276 fflush(0);
277
278 if (!NSK_JNI_VERIFY(jni, (*nextField =
279 NSK_CPP_STUB4(GetFieldID, jni, chainObjectClass,
280 NEXT_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
281 nsk_jvmti_setFailStatus();
282 return NSK_FALSE;
283 }
284 printf("\nFound fieldID: 0x%p - \'%s\' field in chain object class\n",
285 (void*) nextField, NEXT_FIELD_NAME);
286 fflush(0);
287
288 if (!NSK_JNI_VERIFY(jni, (*rootObjectPtr =
289 NSK_CPP_STUB3(GetStaticObjectField, jni,
290 debugeeClass, rootObjectField)) != NULL)) {
291 nsk_jvmti_setFailStatus();
292 return NSK_FALSE;
293 }
294 printf("\nFound root object: 0x%p\n", (void*) *rootObjectPtr);
295 fflush(0);
296
297 if (!NSK_JNI_VERIFY(jni, (*rootObjectPtr =
298 NSK_CPP_STUB2(NewGlobalRef, jni, *rootObjectPtr)) != NULL)) {
299 nsk_jvmti_setFailStatus();
300 return NSK_FALSE;
301 }
302 printf("Created root object global ref: 0x%p\n", (void*)*rootObjectPtr);
303 fflush(0);
304
305 return NSK_TRUE;
306 } /* getFieldsAndObjects */
307
308
309 /** Obtain chain of tested objects and tag them recursively. */
310 static int getAndTagChainObjects(
311 jvmtiEnv* jvmti,
312 JNIEnv* jni,
313 jobject currObj,
314 jfieldID refField,
315 jfieldID nextField,
316 int count,
317 ObjectDesc objectDescList[],
318 jlong tag,
319 int reachable)
320 {
321 jobject nextObj = NULL;
322 jlong objTag = (reachable ? tag : -tag);
323
324 if (count <= 0) {
325 return NSK_TRUE;
326 }
327
328 count--;
329 tag++;
330
331 if (!NSK_JNI_VERIFY(jni, (nextObj =
332 NSK_CPP_STUB3(GetObjectField, jni, currObj, refField)) != NULL)) {
333 nsk_jvmti_setFailStatus();
334 return NSK_FALSE;
335 }
336
337 objectDescList[count].tag = objTag;
338 if (reachable) {
339 objectDescList[count].exp_found++;
340 }
341
342 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, nextObj, objTag))) {
343 nsk_jvmti_setFailStatus();
344 }
345 printf(" tag=%-5ld object=0x%p\n", (long)objTag, (void*)nextObj);
346 fflush(0);
347
348 /* To continue traversing objects in the chain */
349 if (!getAndTagChainObjects(jvmti,
350 jni,
351 nextObj,
352 nextField,
353 nextField,
354 count,
355 objectDescList,
356 tag,
357 reachable)
358 ) {
359 return NSK_FALSE;
360 }
361
362 NSK_TRACE(NSK_CPP_STUB2(DeleteLocalRef, jni, nextObj));
363
364 return NSK_TRUE;
365 } /* getAndTagChainObjects */
366
367 /** Obtain all tested objects from debugee class and tag them recursively. */
368 static int getAndTagTestedObjects(
369 jvmtiEnv* jvmti,
370 JNIEnv* jni,
371 int chainLength,
372 int* objectsCount,
373 ObjectDesc** objectDescList,
374 jobject* rootObjectPtr)
375 {
376 jclass debugeeClass = NULL;
377 jclass rootObjectClass = NULL;
378 jclass chainObjectClass = NULL;
379
380 jfieldID reachableChainField = NULL;
381 jfieldID unreachableChainField = NULL;
382 jfieldID nextField = NULL;
394 &rootObjectClass,
395 &chainObjectClass) == NSK_FALSE) {
396 return NSK_FALSE;
397 }
398
399 if (getFieldsAndObjects(jvmti,
400 jni,
401 debugeeClass,
402 rootObjectClass,
403 chainObjectClass,
404 rootObjectPtr,
405 &reachableChainField,
406 &unreachableChainField,
407 &nextField) == NSK_FALSE) {
408 return NSK_FALSE;
409 }
410
411 printf("\nObtain and tag chain objects:\n");
412 printf(" root tested object:\n");
413
414 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti,
415 *rootObjectPtr,
416 ROOT_OBJECT_TAG))
417 ) {
418 nsk_jvmti_setFailStatus();
419 }
420 printf(" tag=%-5ld object = 0x%p\n",
421 (long) ROOT_OBJECT_TAG, (void*) *rootObjectPtr);
422
423 printf(" reachable objects chain: %d objects\n", chainLength);
424 fflush(0);
425
426 if (!getAndTagChainObjects(jvmti,
427 jni,
428 *rootObjectPtr,
429 reachableChainField,
430 nextField,
431 chainLength,
432 (*objectDescList) + 1,
433 CHAIN_OBJECT_TAG,
434 NSK_TRUE) /* reachable objects */
435 ) {
436 nsk_jvmti_setFailStatus();
514 if (objectDescList[idx].found > 0) {
515 NSK_COMPLAIN0("Unreachable object was iterated\n");
516 nsk_jvmti_setFailStatus();
517 }
518 fflush(0);
519 }
520
521 return NSK_TRUE;
522 } /* checkTestedObjects */
523
524
525 /** Release references to the tested objects and free allocated memory. */
526 static int releaseTestedObjects(jvmtiEnv* jvmti,
527 JNIEnv* jni,
528 int chainLength,
529 ObjectDesc* objectDescList,
530 jobject rootObject)
531 {
532 if (rootObject != NULL) {
533 printf("Release object reference to root tested object: 0x%p\n", rootObject);
534 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, rootObject));
535 }
536
537 if (objectDescList != NULL) {
538 printf("Deallocate objects list: 0x%p\n", (void*)objectDescList);
539 if (!NSK_JVMTI_VERIFY(
540 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)objectDescList))) {
541 nsk_jvmti_setFailStatus();
542 }
543 }
544
545 fflush(0);
546 return NSK_TRUE;
547 } /* releaseTestedObjects */
548
549
550 /* ============================================================================= */
551
552 /** heapReferenceCallback for heap iterator. */
553 jint JNICALL heapReferenceCallback(
554 jvmtiHeapReferenceKind reference_kind,
555 const jvmtiHeapReferenceInfo* reference_info,
556 jlong class_tag,
557 jlong referrer_class_tag,
558 jlong size,
559 jlong* tag_ptr,
560 jlong* referrer_tag_ptr,
769 &objectsCount,
770 &objectDescList,
771 &rootObject))
772 ) {
773 return;
774 }
775
776 printf(">>> Let debugee to clean links to unreachable objects\n");
777 fflush(0);
778
779 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) {
780 return;
781 }
782 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
783 return;
784 }
785
786 printf(">>> Start iteration from root tested object: 0x%p\n\n", rootObject);
787 fflush(0);
788
789 if (!NSK_JVMTI_VERIFY(
790 NSK_CPP_STUB6(FollowReferences, jvmti,
791 (jint) 0, /* heap_filter */
792 (jclass) NULL, /* class */
793 rootObject, /* initial_object */
794 &heapCallbacks,
795 (const void *) &fakeUserData))
796 ) {
797 nsk_jvmti_setFailStatus();
798 return;
799 }
800
801 printf(">>> Check if reachable objects were iterated:\n");
802 fflush(0);
803
804 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
805 nsk_jvmti_setFailStatus();
806 }
807
808 printf(">>> Clean used data\n");
809 fflush(0);
810
811 if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, chainLength,
812 objectDescList, rootObject))) {
813 return;
814 }
815
816 printf(">>> Let debugee to finish\n");
839 jvmtiEnv* jvmti = NULL;
840
841 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) {
842 return JNI_ERR;
843 }
844 timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
845
846 chainLength = nsk_jvmti_findOptionIntValue("objects", DEFAULT_CHAIN_LENGTH);
847 if (!NSK_VERIFY(chainLength > 0))
848 return JNI_ERR;
849
850 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) {
851 return JNI_ERR;
852 }
853
854 {
855 jvmtiCapabilities caps;
856
857 memset(&caps, 0, sizeof(caps));
858 caps.can_tag_objects = 1;
859 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) {
860 return JNI_ERR;
861 }
862 }
863
864 /* Setting Heap Callbacks */
865 heapCallbacks.heap_iteration_callback = NULL;
866 heapCallbacks.heap_reference_callback = heapReferenceCallback;
867 heapCallbacks.primitive_field_callback = primitiveFieldCallback;
868 heapCallbacks.array_primitive_value_callback = arrayPrimitiveValueCallback;
869 heapCallbacks.string_primitive_value_callback = stringPrimitiveValueCallback;
870
871 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) {
872 return JNI_ERR;
873 }
874
875 return JNI_OK;
876 } /* Agent_OnLoad */
877
878
879 /* ============================================================================= */
|
125 default:
126 // TODO: check that realy should be done w/ other jvmtiHeapReferenceKind
127 break;
128 }
129
130 return referrer_index;
131 } /* get_reference_index */
132
133
134 /** Initialize objectDescList. */
135 static int initObjectDescList(jvmtiEnv* jvmti,
136 int chainLength,
137 int* objectsCount,
138 ObjectDesc** objectDescList)
139 {
140 /* root object + reachable and unreachable object chains */
141 *objectsCount = 1 + 2 * chainLength;
142
143 printf("Allocate memory for objects list: %d objects\n", *objectsCount);
144 fflush(0);
145 if (!NSK_JVMTI_VERIFY(jvmti->Allocate((*objectsCount * sizeof(ObjectDesc)),
146 (unsigned char**) objectDescList))) {
147 nsk_jvmti_setFailStatus();
148 return NSK_FALSE;
149 }
150 printf(" ... allocated array: 0x%p\n", (void*)objectDescList);
151 fflush(0);
152
153 {
154 int k;
155 for (k = 0; k < *objectsCount; k++) {
156 (*objectDescList)[k].tag = 0;
157 (*objectDescList)[k].exp_class_tag = CHAIN_CLASS_TAG;
158 (*objectDescList)[k].exp_found = 0;
159 (*objectDescList)[k].found = 0;
160 }
161 }
162 (*objectDescList)[0].exp_class_tag = ROOT_CLASS_TAG;
163 (*objectDescList)[0].tag = ROOT_OBJECT_TAG;
164
165 /* Object with tag=100 must be referenced 2 times */
166 (*objectDescList)[chainLength].exp_found = 1;
167
168
169 return NSK_TRUE;
170 } /* initObjectDescList */
171
172
173 /** Find and tag classes. */
174 static int getAndTagClasses(jvmtiEnv* jvmti,
175 JNIEnv* jni,
176 jclass* debugeeClass,
177 jclass* rootObjectClass,
178 jclass* chainObjectClass)
179 {
180
181 if (!NSK_JNI_VERIFY(jni, (*debugeeClass = jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {
182 nsk_jvmti_setFailStatus();
183 return NSK_FALSE;
184 }
185 printf("\nFound debugee class: 0x%p\n %s\n",
186 (void*) *debugeeClass, DEBUGEE_CLASS_NAME);
187 fflush(0);
188
189 if (!NSK_JNI_VERIFY(jni, (*rootObjectClass =
190 jni->FindClass(ROOT_OBJECT_CLASS_NAME)) != NULL)) {
191 nsk_jvmti_setFailStatus();
192 return NSK_FALSE;
193 }
194
195 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(*rootObjectClass, ROOT_CLASS_TAG))) {
196 nsk_jvmti_setFailStatus();
197 }
198
199 printf("\nFound root object class: 0x%p, tag=%ld\n %s\n",
200 (void*) *rootObjectClass,(long) ROOT_CLASS_TAG,
201 ROOT_OBJECT_CLASS_NAME);
202 fflush(0);
203
204
205 if (!NSK_JNI_VERIFY(jni, (*chainObjectClass =
206 jni->FindClass(CHAIN_OBJECT_CLASS_NAME)) != NULL)) {
207 nsk_jvmti_setFailStatus();
208 return NSK_FALSE;
209 }
210
211 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(*chainObjectClass, CHAIN_CLASS_TAG))) {
212 nsk_jvmti_setFailStatus();
213 }
214 printf("\nFound chain object class: 0x%p, tag=%ld\n %s\n",
215 (void*) *chainObjectClass, (long) CHAIN_CLASS_TAG,
216 CHAIN_OBJECT_CLASS_NAME);
217 fflush(0);
218
219 return NSK_TRUE;
220 } /* getAndTagClasses */
221
222
223 /** Obtain chain of tested objects and tag them recursively. */
224 static int getFieldsAndObjects(jvmtiEnv* jvmti,
225 JNIEnv* jni,
226 jclass debugeeClass,
227 jclass rootObjectClass,
228 jclass chainObjectClass,
229 jobject* rootObjectPtr,
230 jfieldID* reachableChainField,
231 jfieldID* unreachableChainField,
232 jfieldID* nextField)
233 {
234 jfieldID rootObjectField = NULL;
235
236 if (!NSK_JNI_VERIFY(jni, (rootObjectField =
237 jni->GetStaticFieldID(debugeeClass, OBJECT_FIELD_NAME, ROOT_OBJECT_CLASS_SIG)) != NULL)) {
238 nsk_jvmti_setFailStatus();
239 return NSK_FALSE;
240 }
241 printf("\nFound fieldID: 0x%p - \'%s\' static field in debugee class\n",
242 (void*) rootObjectField, OBJECT_FIELD_NAME);
243 fflush(0);
244
245 if (!NSK_JNI_VERIFY(jni, (*reachableChainField =
246 jni->GetFieldID(rootObjectClass, REACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
247 nsk_jvmti_setFailStatus();
248 return NSK_FALSE;
249 }
250 printf("\nFound fieldID: 0x%p - \'%s\' field in root object class\n",
251 (void*) reachableChainField, REACHABLE_CHAIN_FIELD_NAME);
252 fflush(0);
253
254 if (!NSK_JNI_VERIFY(jni, (*unreachableChainField =
255 jni->GetFieldID(rootObjectClass, UNREACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
256 nsk_jvmti_setFailStatus();
257 return NSK_FALSE;
258 }
259
260 printf("\nFound fieldID: 0x%p - \'%s\' field in root object class\n",
261 (void*) unreachableChainField, UNREACHABLE_CHAIN_FIELD_NAME);
262 fflush(0);
263
264 if (!NSK_JNI_VERIFY(jni, (*nextField =
265 jni->GetFieldID(chainObjectClass, NEXT_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
266 nsk_jvmti_setFailStatus();
267 return NSK_FALSE;
268 }
269 printf("\nFound fieldID: 0x%p - \'%s\' field in chain object class\n",
270 (void*) nextField, NEXT_FIELD_NAME);
271 fflush(0);
272
273 if (!NSK_JNI_VERIFY(jni, (*rootObjectPtr =
274 jni->GetStaticObjectField(debugeeClass, rootObjectField)) != NULL)) {
275 nsk_jvmti_setFailStatus();
276 return NSK_FALSE;
277 }
278 printf("\nFound root object: 0x%p\n", (void*) *rootObjectPtr);
279 fflush(0);
280
281 if (!NSK_JNI_VERIFY(jni, (*rootObjectPtr = jni->NewGlobalRef(*rootObjectPtr)) != NULL)) {
282 nsk_jvmti_setFailStatus();
283 return NSK_FALSE;
284 }
285 printf("Created root object global ref: 0x%p\n", (void*)*rootObjectPtr);
286 fflush(0);
287
288 return NSK_TRUE;
289 } /* getFieldsAndObjects */
290
291
292 /** Obtain chain of tested objects and tag them recursively. */
293 static int getAndTagChainObjects(
294 jvmtiEnv* jvmti,
295 JNIEnv* jni,
296 jobject currObj,
297 jfieldID refField,
298 jfieldID nextField,
299 int count,
300 ObjectDesc objectDescList[],
301 jlong tag,
302 int reachable)
303 {
304 jobject nextObj = NULL;
305 jlong objTag = (reachable ? tag : -tag);
306
307 if (count <= 0) {
308 return NSK_TRUE;
309 }
310
311 count--;
312 tag++;
313
314 if (!NSK_JNI_VERIFY(jni, (nextObj = jni->GetObjectField(currObj, refField)) != NULL)) {
315 nsk_jvmti_setFailStatus();
316 return NSK_FALSE;
317 }
318
319 objectDescList[count].tag = objTag;
320 if (reachable) {
321 objectDescList[count].exp_found++;
322 }
323
324 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(nextObj, objTag))) {
325 nsk_jvmti_setFailStatus();
326 }
327 printf(" tag=%-5ld object=0x%p\n", (long)objTag, (void*)nextObj);
328 fflush(0);
329
330 /* To continue traversing objects in the chain */
331 if (!getAndTagChainObjects(jvmti,
332 jni,
333 nextObj,
334 nextField,
335 nextField,
336 count,
337 objectDescList,
338 tag,
339 reachable)
340 ) {
341 return NSK_FALSE;
342 }
343
344 NSK_TRACE(jni->DeleteLocalRef(nextObj));
345
346 return NSK_TRUE;
347 } /* getAndTagChainObjects */
348
349 /** Obtain all tested objects from debugee class and tag them recursively. */
350 static int getAndTagTestedObjects(
351 jvmtiEnv* jvmti,
352 JNIEnv* jni,
353 int chainLength,
354 int* objectsCount,
355 ObjectDesc** objectDescList,
356 jobject* rootObjectPtr)
357 {
358 jclass debugeeClass = NULL;
359 jclass rootObjectClass = NULL;
360 jclass chainObjectClass = NULL;
361
362 jfieldID reachableChainField = NULL;
363 jfieldID unreachableChainField = NULL;
364 jfieldID nextField = NULL;
376 &rootObjectClass,
377 &chainObjectClass) == NSK_FALSE) {
378 return NSK_FALSE;
379 }
380
381 if (getFieldsAndObjects(jvmti,
382 jni,
383 debugeeClass,
384 rootObjectClass,
385 chainObjectClass,
386 rootObjectPtr,
387 &reachableChainField,
388 &unreachableChainField,
389 &nextField) == NSK_FALSE) {
390 return NSK_FALSE;
391 }
392
393 printf("\nObtain and tag chain objects:\n");
394 printf(" root tested object:\n");
395
396 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(*rootObjectPtr, ROOT_OBJECT_TAG))
397 ) {
398 nsk_jvmti_setFailStatus();
399 }
400 printf(" tag=%-5ld object = 0x%p\n",
401 (long) ROOT_OBJECT_TAG, (void*) *rootObjectPtr);
402
403 printf(" reachable objects chain: %d objects\n", chainLength);
404 fflush(0);
405
406 if (!getAndTagChainObjects(jvmti,
407 jni,
408 *rootObjectPtr,
409 reachableChainField,
410 nextField,
411 chainLength,
412 (*objectDescList) + 1,
413 CHAIN_OBJECT_TAG,
414 NSK_TRUE) /* reachable objects */
415 ) {
416 nsk_jvmti_setFailStatus();
494 if (objectDescList[idx].found > 0) {
495 NSK_COMPLAIN0("Unreachable object was iterated\n");
496 nsk_jvmti_setFailStatus();
497 }
498 fflush(0);
499 }
500
501 return NSK_TRUE;
502 } /* checkTestedObjects */
503
504
505 /** Release references to the tested objects and free allocated memory. */
506 static int releaseTestedObjects(jvmtiEnv* jvmti,
507 JNIEnv* jni,
508 int chainLength,
509 ObjectDesc* objectDescList,
510 jobject rootObject)
511 {
512 if (rootObject != NULL) {
513 printf("Release object reference to root tested object: 0x%p\n", rootObject);
514 NSK_TRACE(jni->DeleteGlobalRef(rootObject));
515 }
516
517 if (objectDescList != NULL) {
518 printf("Deallocate objects list: 0x%p\n", (void*)objectDescList);
519 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)objectDescList))) {
520 nsk_jvmti_setFailStatus();
521 }
522 }
523
524 fflush(0);
525 return NSK_TRUE;
526 } /* releaseTestedObjects */
527
528
529 /* ============================================================================= */
530
531 /** heapReferenceCallback for heap iterator. */
532 jint JNICALL heapReferenceCallback(
533 jvmtiHeapReferenceKind reference_kind,
534 const jvmtiHeapReferenceInfo* reference_info,
535 jlong class_tag,
536 jlong referrer_class_tag,
537 jlong size,
538 jlong* tag_ptr,
539 jlong* referrer_tag_ptr,
748 &objectsCount,
749 &objectDescList,
750 &rootObject))
751 ) {
752 return;
753 }
754
755 printf(">>> Let debugee to clean links to unreachable objects\n");
756 fflush(0);
757
758 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) {
759 return;
760 }
761 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
762 return;
763 }
764
765 printf(">>> Start iteration from root tested object: 0x%p\n\n", rootObject);
766 fflush(0);
767
768 if (!NSK_JVMTI_VERIFY(jvmti->FollowReferences((jint) 0, /* heap_filter */
769 (jclass) NULL, /* class */
770 rootObject, /* initial_object */
771 &heapCallbacks,
772 (const void *) &fakeUserData))) {
773 nsk_jvmti_setFailStatus();
774 return;
775 }
776
777 printf(">>> Check if reachable objects were iterated:\n");
778 fflush(0);
779
780 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
781 nsk_jvmti_setFailStatus();
782 }
783
784 printf(">>> Clean used data\n");
785 fflush(0);
786
787 if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, chainLength,
788 objectDescList, rootObject))) {
789 return;
790 }
791
792 printf(">>> Let debugee to finish\n");
815 jvmtiEnv* jvmti = NULL;
816
817 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) {
818 return JNI_ERR;
819 }
820 timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
821
822 chainLength = nsk_jvmti_findOptionIntValue("objects", DEFAULT_CHAIN_LENGTH);
823 if (!NSK_VERIFY(chainLength > 0))
824 return JNI_ERR;
825
826 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) {
827 return JNI_ERR;
828 }
829
830 {
831 jvmtiCapabilities caps;
832
833 memset(&caps, 0, sizeof(caps));
834 caps.can_tag_objects = 1;
835 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
836 return JNI_ERR;
837 }
838 }
839
840 /* Setting Heap Callbacks */
841 heapCallbacks.heap_iteration_callback = NULL;
842 heapCallbacks.heap_reference_callback = heapReferenceCallback;
843 heapCallbacks.primitive_field_callback = primitiveFieldCallback;
844 heapCallbacks.array_primitive_value_callback = arrayPrimitiveValueCallback;
845 heapCallbacks.string_primitive_value_callback = stringPrimitiveValueCallback;
846
847 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) {
848 return JNI_ERR;
849 }
850
851 return JNI_OK;
852 } /* Agent_OnLoad */
853
854
855 /* ============================================================================= */
|