121 #define DEREF(ptr) (((ptr) == NULL ? 0 : *(ptr)))
122
123
124 /* ============================================================================= */
125
126 /** Obtain chain of tested objects and tag them recursively. */
127 static int getChainObjects(jvmtiEnv* jvmti, JNIEnv* jni, jobject firstObject,
128 jfieldID firstField, const char firstFieldName[],
129 jfieldID nextField, const char nextFieldName[],
130 int count, ObjectDesc objectDescList[],
131 jlong tag, int reachable) {
132 jobject obj = NULL;
133 jlong objTag = (reachable ? tag : -tag);
134
135 if (count <= 0)
136 return NSK_TRUE;
137
138 count--;
139 tag++;
140
141 if (!NSK_JNI_VERIFY(jni, (obj =
142 NSK_CPP_STUB3(GetObjectField, jni, firstObject, firstField)) != NULL)) {
143 nsk_jvmti_setFailStatus();
144 return NSK_FALSE;
145 }
146
147 objectDescList[count].tag = objTag;
148
149 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, obj, objTag))) {
150 nsk_jvmti_setFailStatus();
151 }
152 printf(" tag=%-5ld object=0x%p\n", (long)objTag, (void*)obj);
153 fflush(0);
154 if (!getChainObjects(jvmti, jni, obj, nextField, nextFieldName,
155 nextField, nextFieldName,
156 count, objectDescList, tag, reachable)) {
157 return NSK_FALSE;
158 }
159
160 NSK_TRACE(NSK_CPP_STUB2(DeleteLocalRef, jni, obj));
161 return NSK_TRUE;
162 }
163
164 /** Obtain all tested objects from debugee class and tag them recursively. */
165 static int getTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
166 int *objectsCount, ObjectDesc* *objectDescList,
167 jobject* rootObject) {
168 jclass debugeeClass = NULL;
169 jclass rootObjectClass = NULL;
170 jclass chainObjectClass = NULL;
171
172 jfieldID objectField = NULL;
173 jfieldID reachableChainField = NULL;
174 jfieldID unreachableChainField = NULL;
175 jfieldID tailField = NULL;
176
177 *objectsCount = 1 + 2 * chainLength;
178
179 printf("Allocate memory for objects list: %d objects\n", *objectsCount);
180 fflush(0);
181 if (!NSK_JVMTI_VERIFY(
182 NSK_CPP_STUB3(Allocate, jvmti, (*objectsCount * sizeof(ObjectDesc)),
183 (unsigned char**)objectDescList))) {
184 nsk_jvmti_setFailStatus();
185 return NSK_FALSE;
186 }
187 printf(" ... allocated array: 0x%p\n", (void*)objectDescList);
188 fflush(0);
189
190 {
191 int k;
192 for (k = 0; k < *objectsCount; k++) {
193 (*objectDescList)[k].tag = 0;
194 (*objectDescList)[k].exp_class_tag = chainClassTag;
195 (*objectDescList)[k].exp_found = 0;
196 (*objectDescList)[k].found = 0;
197 }
198 }
199 (*objectDescList)[0].exp_class_tag = rootClassTag;
200
201 printf("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);
202 fflush(0);
203 if (!NSK_JNI_VERIFY(jni, (debugeeClass =
204 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) {
205 nsk_jvmti_setFailStatus();
206 return NSK_FALSE;
207 }
208 printf(" ... found class: 0x%p\n", (void*)debugeeClass);
209
210 printf("Find root object class: %s\n", ROOT_OBJECT_CLASS_NAME);
211 fflush(0);
212 if (!NSK_JNI_VERIFY(jni, (rootObjectClass =
213 NSK_CPP_STUB2(FindClass, jni, ROOT_OBJECT_CLASS_NAME)) != NULL)) {
214 nsk_jvmti_setFailStatus();
215 return NSK_FALSE;
216 }
217 printf(" ... found class: 0x%p\n", (void*)rootObjectClass);
218
219 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, rootObjectClass, rootClassTag))) {
220 nsk_jvmti_setFailStatus();
221 }
222 printf(" tag=%-5ld rootClass=0x%p\n",
223 (long)rootClassTag, (void*)rootObjectClass);
224
225 printf("Find chain object class: %s\n", CHAIN_OBJECT_CLASS_NAME);
226 fflush(0);
227 if (!NSK_JNI_VERIFY(jni, (chainObjectClass =
228 NSK_CPP_STUB2(FindClass, jni, CHAIN_OBJECT_CLASS_NAME)) != NULL)) {
229 nsk_jvmti_setFailStatus();
230 return NSK_FALSE;
231 }
232 printf(" ... found class: 0x%p\n",
233 (void*)chainObjectClass);
234
235 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, chainObjectClass, chainClassTag))) {
236 nsk_jvmti_setFailStatus();
237 }
238 printf(" tag=%-5ld chainClass=0x%p\n",
239 (long)chainClassTag, (void*)chainObjectClass);
240
241 printf("Find static field in debugee class: %s\n", OBJECT_FIELD_NAME);
242 fflush(0);
243 if (!NSK_JNI_VERIFY(jni, (objectField =
244 NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass,
245 OBJECT_FIELD_NAME, ROOT_OBJECT_CLASS_SIG)) != NULL)) {
246 nsk_jvmti_setFailStatus();
247 return NSK_FALSE;
248 }
249 printf(" ... got fieldID: 0x%p\n", (void*)objectField);
250
251 printf("Find instance field in root object class: %s\n", REACHABLE_CHAIN_FIELD_NAME);
252 fflush(0);
253 if (!NSK_JNI_VERIFY(jni, (reachableChainField =
254 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass,
255 REACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
256 nsk_jvmti_setFailStatus();
257 return NSK_FALSE;
258 }
259 printf(" ... got fieldID: 0x%p\n", (void*)reachableChainField);
260
261 printf("Find instance field in root object class: %s\n", UNREACHABLE_CHAIN_FIELD_NAME);
262 fflush(0);
263 if (!NSK_JNI_VERIFY(jni, (unreachableChainField =
264 NSK_CPP_STUB4(GetFieldID, jni, rootObjectClass,
265 UNREACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
266 nsk_jvmti_setFailStatus();
267 return NSK_FALSE;
268 }
269 printf(" ... got fieldID: 0x%p\n", (void*)unreachableChainField);
270
271 printf("Find instance field in chain object class: %s\n", TAIL_FIELD_NAME);
272 fflush(0);
273 if (!NSK_JNI_VERIFY(jni, (tailField =
274 NSK_CPP_STUB4(GetFieldID, jni, chainObjectClass,
275 TAIL_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
276 nsk_jvmti_setFailStatus();
277 return NSK_FALSE;
278 }
279 printf(" ... got fieldID: 0x%p\n", (void*)tailField);
280
281 printf("Get root object from static field: %s\n", OBJECT_FIELD_NAME);
282 fflush(0);
283 if (!NSK_JNI_VERIFY(jni, (*rootObject =
284 NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass,
285 objectField)) != NULL)) {
286 nsk_jvmti_setFailStatus();
287 return NSK_FALSE;
288 }
289 printf(" ... got object: 0x%p\n", (void*)*rootObject);
290 fflush(0);
291
292 if (!NSK_JNI_VERIFY(jni, (*rootObject =
293 NSK_CPP_STUB2(NewGlobalRef, jni, *rootObject)) != NULL)) {
294 nsk_jvmti_setFailStatus();
295 return NSK_FALSE;
296 }
297 printf(" ... global ref: 0x%p\n", (void*)*rootObject);
298
299 printf("Obtain and tag chain objects:\n");
300
301 printf(" root tested object\n");
302 fflush(0);
303 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetTag, jvmti, *rootObject, rootObjectTag))) {
304 nsk_jvmti_setFailStatus();
305 }
306 printf(" tag=%-5ld object=0x%p\n",
307 (long)rootObjectTag, (void*)*rootObject);
308
309 /* Root object must be reported 1 time */
310 (*objectDescList)[0].exp_found = 1;
311 (*objectDescList)[0].tag = rootObjectTag;
312
313 printf(" reachable objects chain: %d objects\n", chainLength);
314 fflush(0);
315 if (!getChainObjects(jvmti, jni, *rootObject,
316 reachableChainField, REACHABLE_CHAIN_FIELD_NAME,
317 tailField, TAIL_FIELD_NAME,
318 chainLength, (*objectDescList) + 1,
319 chainObjectTag, NSK_TRUE)) {
320 nsk_jvmti_setFailStatus();
321 return NSK_FALSE;
322 }
323
389 " expected to iterate: %d times\n"
390 " iterated: %d times\n",
391 (long) objectDescList[idx].tag,
392 objectDescList[idx].exp_found,
393 objectDescList[idx].found);
394 if (objectDescList[idx].found > 0 && objectDescList[idx].exp_found == 0) {
395 NSK_COMPLAIN0("Unreachable object was iterated\n");
396 nsk_jvmti_setFailStatus();
397 }
398 fflush(0);
399 }
400
401 return NSK_TRUE;
402 }
403
404 /** Release references to the tested objects and free allocated memory. */
405 static int releaseTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
406 ObjectDesc* objectDescList, jobject rootObject) {
407 if (rootObject != NULL) {
408 printf("Release object reference to root tested object: 0x%p\n", rootObject);
409 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, rootObject));
410 }
411
412 if (objectDescList != NULL) {
413 printf("Deallocate objects list: 0x%p\n", (void*)objectDescList);
414 if (!NSK_JVMTI_VERIFY(
415 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)objectDescList))) {
416 nsk_jvmti_setFailStatus();
417 }
418 }
419
420 fflush(0);
421 return NSK_TRUE;
422 }
423
424 /* ============================================================================= */
425
426 /* Some diagnostics happen in the first FollowReferences call only */
427 static int first_followref = 1;
428
429 typedef struct ThreadDescStruct {
430 jlong tag;
431 jlong id;
432 } ThreadDesc;
433
434 #define MAX_THREADS 1024
435 static ThreadDesc thrDesc [MAX_THREADS] = {};
932
933 printf(">>> Let debugee to clean links to unreachable objects\n");
934 fflush(0);
935 {
936 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) {
937 return;
938 }
939 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
940 return;
941 }
942 }
943
944 if (!NSK_JVMTI_VERIFY(setTagForTargetThread(jvmti, TARG_THREAD_TAG))) {
945 nsk_jvmti_setFailStatus();
946 return;
947 }
948
949 printf("\n\n>>> Start 1-st iteration starting from the heap root\n");
950 fflush(0);
951 {
952 if (!NSK_JVMTI_VERIFY(
953 NSK_CPP_STUB6(FollowReferences, jvmti,
954 (jint) 0, /* heap_filter */
955 (jclass) NULL, /* class */
956 (jobject) NULL, /* initial_object */
957 &heapCallbacks,
958 (const void *) &fakeUserData)))
959 {
960 nsk_jvmti_setFailStatus();
961 return;
962 }
963 }
964
965 printf(">>> Check if reachable objects were iterated\n");
966 fflush(0);
967 {
968 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
969 nsk_jvmti_setFailStatus();
970 }
971 }
972
973 { /* Reinstall the expectations */
974 int k;
975 for (k = 0; k < objectsCount; k++) {
976 (objectDescList)[k].exp_found = 0;
977 (objectDescList)[k].found = 0;
978 }
979 /* Heap root object must be reported 2 times */
980 objectDescList[0].exp_found = 2;
981
982 /* First unreachable object must be reported once
983 * as JVMTI_HEAP_REFERENCE_STACK_LOCAL */
984 objectDescList[2 * chainLength].exp_found = 1;
985 }
986
987 printf("\n\n>>> Start 2-nd iteration starting from the heap root\n");
988 fflush(0);
989 first_followref = 0;
990 {
991 jint heap_filter = JVMTI_HEAP_FILTER_UNTAGGED
992 | JVMTI_HEAP_FILTER_CLASS_UNTAGGED;
993 if (!NSK_JVMTI_VERIFY(
994 NSK_CPP_STUB6(FollowReferences, jvmti,
995 heap_filter,
996 (jclass) NULL, /* class */
997 (jobject) NULL, /* initial_object */
998 &heapCallbacks,
999 (const void *) &fakeUserData)))
1000 {
1001 nsk_jvmti_setFailStatus();
1002 return;
1003 }
1004 }
1005
1006 printf(">>> Check that both reachable and unreachable "
1007 "objects were not iterated\n");
1008 fflush(0);
1009 {
1010 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
1011 nsk_jvmti_setFailStatus();
1012 }
1013 }
1014
1015
1016 printf(">>> Clean used data\n");
1017 fflush(0);
1018 {
1019 if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, chainLength,
1020 objectDescList, rootObject))) {
1069 printf("Unknown option value: info=%s\n", infoOpt);
1070 fflush(0);
1071 return JNI_ERR;
1072 }
1073 }
1074 }
1075
1076 chainLength = nsk_jvmti_findOptionIntValue("objects", DEFAULT_CHAIN_LENGTH);
1077 if (!NSK_VERIFY(chainLength > 0))
1078 return JNI_ERR;
1079
1080 if (!NSK_VERIFY((jvmti =
1081 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
1082 return JNI_ERR;
1083
1084 {
1085 jvmtiCapabilities caps;
1086
1087 memset(&caps, 0, sizeof(caps));
1088 caps.can_tag_objects = 1;
1089 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) {
1090 return JNI_ERR;
1091 }
1092 }
1093
1094 /* Setting Heap Callbacks */
1095 heapCallbacks.heap_iteration_callback = NULL;
1096 heapCallbacks.heap_reference_callback = heapReferenceCallback;
1097 heapCallbacks.primitive_field_callback = primitiveFieldCallback;
1098 heapCallbacks.array_primitive_value_callback = arrayPrimitiveValueCallback;
1099 heapCallbacks.string_primitive_value_callback = stringPrimitiveValueCallback;
1100
1101 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
1102 return JNI_ERR;
1103
1104 return JNI_OK;
1105 }
1106
1107 /* ============================================================================= */
1108
1109 }
|
121 #define DEREF(ptr) (((ptr) == NULL ? 0 : *(ptr)))
122
123
124 /* ============================================================================= */
125
126 /** Obtain chain of tested objects and tag them recursively. */
127 static int getChainObjects(jvmtiEnv* jvmti, JNIEnv* jni, jobject firstObject,
128 jfieldID firstField, const char firstFieldName[],
129 jfieldID nextField, const char nextFieldName[],
130 int count, ObjectDesc objectDescList[],
131 jlong tag, int reachable) {
132 jobject obj = NULL;
133 jlong objTag = (reachable ? tag : -tag);
134
135 if (count <= 0)
136 return NSK_TRUE;
137
138 count--;
139 tag++;
140
141 if (!NSK_JNI_VERIFY(jni, (obj = jni->GetObjectField(firstObject, firstField)) != NULL)) {
142 nsk_jvmti_setFailStatus();
143 return NSK_FALSE;
144 }
145
146 objectDescList[count].tag = objTag;
147
148 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(obj, objTag))) {
149 nsk_jvmti_setFailStatus();
150 }
151 printf(" tag=%-5ld object=0x%p\n", (long)objTag, (void*)obj);
152 fflush(0);
153 if (!getChainObjects(jvmti, jni, obj, nextField, nextFieldName,
154 nextField, nextFieldName,
155 count, objectDescList, tag, reachable)) {
156 return NSK_FALSE;
157 }
158
159 NSK_TRACE(jni->DeleteLocalRef(obj));
160 return NSK_TRUE;
161 }
162
163 /** Obtain all tested objects from debugee class and tag them recursively. */
164 static int getTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
165 int *objectsCount, ObjectDesc* *objectDescList,
166 jobject* rootObject) {
167 jclass debugeeClass = NULL;
168 jclass rootObjectClass = NULL;
169 jclass chainObjectClass = NULL;
170
171 jfieldID objectField = NULL;
172 jfieldID reachableChainField = NULL;
173 jfieldID unreachableChainField = NULL;
174 jfieldID tailField = NULL;
175
176 *objectsCount = 1 + 2 * chainLength;
177
178 printf("Allocate memory for objects list: %d objects\n", *objectsCount);
179 fflush(0);
180 if (!NSK_JVMTI_VERIFY(jvmti->Allocate((*objectsCount * sizeof(ObjectDesc)),
181 (unsigned char**)objectDescList))) {
182 nsk_jvmti_setFailStatus();
183 return NSK_FALSE;
184 }
185 printf(" ... allocated array: 0x%p\n", (void*)objectDescList);
186 fflush(0);
187
188 {
189 int k;
190 for (k = 0; k < *objectsCount; k++) {
191 (*objectDescList)[k].tag = 0;
192 (*objectDescList)[k].exp_class_tag = chainClassTag;
193 (*objectDescList)[k].exp_found = 0;
194 (*objectDescList)[k].found = 0;
195 }
196 }
197 (*objectDescList)[0].exp_class_tag = rootClassTag;
198
199 printf("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);
200 fflush(0);
201 if (!NSK_JNI_VERIFY(jni, (debugeeClass = jni->FindClass(DEBUGEE_CLASS_NAME)) != NULL)) {
202 nsk_jvmti_setFailStatus();
203 return NSK_FALSE;
204 }
205 printf(" ... found class: 0x%p\n", (void*)debugeeClass);
206
207 printf("Find root object class: %s\n", ROOT_OBJECT_CLASS_NAME);
208 fflush(0);
209 if (!NSK_JNI_VERIFY(jni, (rootObjectClass = jni->FindClass(ROOT_OBJECT_CLASS_NAME)) != NULL)) {
210 nsk_jvmti_setFailStatus();
211 return NSK_FALSE;
212 }
213 printf(" ... found class: 0x%p\n", (void*)rootObjectClass);
214
215 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(rootObjectClass, rootClassTag))) {
216 nsk_jvmti_setFailStatus();
217 }
218 printf(" tag=%-5ld rootClass=0x%p\n",
219 (long)rootClassTag, (void*)rootObjectClass);
220
221 printf("Find chain object class: %s\n", CHAIN_OBJECT_CLASS_NAME);
222 fflush(0);
223 if (!NSK_JNI_VERIFY(jni, (chainObjectClass =
224 jni->FindClass(CHAIN_OBJECT_CLASS_NAME)) != NULL)) {
225 nsk_jvmti_setFailStatus();
226 return NSK_FALSE;
227 }
228 printf(" ... found class: 0x%p\n",
229 (void*)chainObjectClass);
230
231 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(chainObjectClass, chainClassTag))) {
232 nsk_jvmti_setFailStatus();
233 }
234 printf(" tag=%-5ld chainClass=0x%p\n",
235 (long)chainClassTag, (void*)chainObjectClass);
236
237 printf("Find static field in debugee class: %s\n", OBJECT_FIELD_NAME);
238 fflush(0);
239 if (!NSK_JNI_VERIFY(jni, (objectField =
240 jni->GetStaticFieldID(debugeeClass, OBJECT_FIELD_NAME, ROOT_OBJECT_CLASS_SIG)) != NULL)) {
241 nsk_jvmti_setFailStatus();
242 return NSK_FALSE;
243 }
244 printf(" ... got fieldID: 0x%p\n", (void*)objectField);
245
246 printf("Find instance field in root object class: %s\n", REACHABLE_CHAIN_FIELD_NAME);
247 fflush(0);
248 if (!NSK_JNI_VERIFY(jni, (reachableChainField =
249 jni->GetFieldID(rootObjectClass, REACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
250 nsk_jvmti_setFailStatus();
251 return NSK_FALSE;
252 }
253 printf(" ... got fieldID: 0x%p\n", (void*)reachableChainField);
254
255 printf("Find instance field in root object class: %s\n", UNREACHABLE_CHAIN_FIELD_NAME);
256 fflush(0);
257 if (!NSK_JNI_VERIFY(jni, (unreachableChainField =
258 jni->GetFieldID(rootObjectClass, UNREACHABLE_CHAIN_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
259 nsk_jvmti_setFailStatus();
260 return NSK_FALSE;
261 }
262 printf(" ... got fieldID: 0x%p\n", (void*)unreachableChainField);
263
264 printf("Find instance field in chain object class: %s\n", TAIL_FIELD_NAME);
265 fflush(0);
266 if (!NSK_JNI_VERIFY(jni, (tailField =
267 jni->GetFieldID(chainObjectClass, TAIL_FIELD_NAME, CHAIN_OBJECT_CLASS_SIG)) != NULL)) {
268 nsk_jvmti_setFailStatus();
269 return NSK_FALSE;
270 }
271 printf(" ... got fieldID: 0x%p\n", (void*)tailField);
272
273 printf("Get root object from static field: %s\n", OBJECT_FIELD_NAME);
274 fflush(0);
275 if (!NSK_JNI_VERIFY(jni, (*rootObject =
276 jni->GetStaticObjectField(debugeeClass, objectField)) != NULL)) {
277 nsk_jvmti_setFailStatus();
278 return NSK_FALSE;
279 }
280 printf(" ... got object: 0x%p\n", (void*)*rootObject);
281 fflush(0);
282
283 if (!NSK_JNI_VERIFY(jni, (*rootObject = jni->NewGlobalRef(*rootObject)) != NULL)) {
284 nsk_jvmti_setFailStatus();
285 return NSK_FALSE;
286 }
287 printf(" ... global ref: 0x%p\n", (void*)*rootObject);
288
289 printf("Obtain and tag chain objects:\n");
290
291 printf(" root tested object\n");
292 fflush(0);
293 if (!NSK_JVMTI_VERIFY(jvmti->SetTag(*rootObject, rootObjectTag))) {
294 nsk_jvmti_setFailStatus();
295 }
296 printf(" tag=%-5ld object=0x%p\n",
297 (long)rootObjectTag, (void*)*rootObject);
298
299 /* Root object must be reported 1 time */
300 (*objectDescList)[0].exp_found = 1;
301 (*objectDescList)[0].tag = rootObjectTag;
302
303 printf(" reachable objects chain: %d objects\n", chainLength);
304 fflush(0);
305 if (!getChainObjects(jvmti, jni, *rootObject,
306 reachableChainField, REACHABLE_CHAIN_FIELD_NAME,
307 tailField, TAIL_FIELD_NAME,
308 chainLength, (*objectDescList) + 1,
309 chainObjectTag, NSK_TRUE)) {
310 nsk_jvmti_setFailStatus();
311 return NSK_FALSE;
312 }
313
379 " expected to iterate: %d times\n"
380 " iterated: %d times\n",
381 (long) objectDescList[idx].tag,
382 objectDescList[idx].exp_found,
383 objectDescList[idx].found);
384 if (objectDescList[idx].found > 0 && objectDescList[idx].exp_found == 0) {
385 NSK_COMPLAIN0("Unreachable object was iterated\n");
386 nsk_jvmti_setFailStatus();
387 }
388 fflush(0);
389 }
390
391 return NSK_TRUE;
392 }
393
394 /** Release references to the tested objects and free allocated memory. */
395 static int releaseTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int chainLength,
396 ObjectDesc* objectDescList, jobject rootObject) {
397 if (rootObject != NULL) {
398 printf("Release object reference to root tested object: 0x%p\n", rootObject);
399 NSK_TRACE(jni->DeleteGlobalRef(rootObject));
400 }
401
402 if (objectDescList != NULL) {
403 printf("Deallocate objects list: 0x%p\n", (void*)objectDescList);
404 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)objectDescList))) {
405 nsk_jvmti_setFailStatus();
406 }
407 }
408
409 fflush(0);
410 return NSK_TRUE;
411 }
412
413 /* ============================================================================= */
414
415 /* Some diagnostics happen in the first FollowReferences call only */
416 static int first_followref = 1;
417
418 typedef struct ThreadDescStruct {
419 jlong tag;
420 jlong id;
421 } ThreadDesc;
422
423 #define MAX_THREADS 1024
424 static ThreadDesc thrDesc [MAX_THREADS] = {};
921
922 printf(">>> Let debugee to clean links to unreachable objects\n");
923 fflush(0);
924 {
925 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) {
926 return;
927 }
928 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) {
929 return;
930 }
931 }
932
933 if (!NSK_JVMTI_VERIFY(setTagForTargetThread(jvmti, TARG_THREAD_TAG))) {
934 nsk_jvmti_setFailStatus();
935 return;
936 }
937
938 printf("\n\n>>> Start 1-st iteration starting from the heap root\n");
939 fflush(0);
940 {
941 if (!NSK_JVMTI_VERIFY(jvmti->FollowReferences((jint) 0, /* heap_filter */
942 (jclass) NULL, /* class */
943 (jobject) NULL, /* initial_object */
944 &heapCallbacks,
945 (const void *) &fakeUserData))) {
946 nsk_jvmti_setFailStatus();
947 return;
948 }
949 }
950
951 printf(">>> Check if reachable objects were iterated\n");
952 fflush(0);
953 {
954 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
955 nsk_jvmti_setFailStatus();
956 }
957 }
958
959 { /* Reinstall the expectations */
960 int k;
961 for (k = 0; k < objectsCount; k++) {
962 (objectDescList)[k].exp_found = 0;
963 (objectDescList)[k].found = 0;
964 }
965 /* Heap root object must be reported 2 times */
966 objectDescList[0].exp_found = 2;
967
968 /* First unreachable object must be reported once
969 * as JVMTI_HEAP_REFERENCE_STACK_LOCAL */
970 objectDescList[2 * chainLength].exp_found = 1;
971 }
972
973 printf("\n\n>>> Start 2-nd iteration starting from the heap root\n");
974 fflush(0);
975 first_followref = 0;
976 {
977 jint heap_filter = JVMTI_HEAP_FILTER_UNTAGGED
978 | JVMTI_HEAP_FILTER_CLASS_UNTAGGED;
979 if (!NSK_JVMTI_VERIFY(jvmti->FollowReferences(heap_filter,
980 (jclass) NULL, /* class */
981 (jobject) NULL, /* initial_object */
982 &heapCallbacks,
983 (const void *) &fakeUserData))) {
984 nsk_jvmti_setFailStatus();
985 return;
986 }
987 }
988
989 printf(">>> Check that both reachable and unreachable "
990 "objects were not iterated\n");
991 fflush(0);
992 {
993 if (!checkTestedObjects(jvmti, jni, chainLength, objectDescList)) {
994 nsk_jvmti_setFailStatus();
995 }
996 }
997
998
999 printf(">>> Clean used data\n");
1000 fflush(0);
1001 {
1002 if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, chainLength,
1003 objectDescList, rootObject))) {
1052 printf("Unknown option value: info=%s\n", infoOpt);
1053 fflush(0);
1054 return JNI_ERR;
1055 }
1056 }
1057 }
1058
1059 chainLength = nsk_jvmti_findOptionIntValue("objects", DEFAULT_CHAIN_LENGTH);
1060 if (!NSK_VERIFY(chainLength > 0))
1061 return JNI_ERR;
1062
1063 if (!NSK_VERIFY((jvmti =
1064 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
1065 return JNI_ERR;
1066
1067 {
1068 jvmtiCapabilities caps;
1069
1070 memset(&caps, 0, sizeof(caps));
1071 caps.can_tag_objects = 1;
1072 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
1073 return JNI_ERR;
1074 }
1075 }
1076
1077 /* Setting Heap Callbacks */
1078 heapCallbacks.heap_iteration_callback = NULL;
1079 heapCallbacks.heap_reference_callback = heapReferenceCallback;
1080 heapCallbacks.primitive_field_callback = primitiveFieldCallback;
1081 heapCallbacks.array_primitive_value_callback = arrayPrimitiveValueCallback;
1082 heapCallbacks.string_primitive_value_callback = stringPrimitiveValueCallback;
1083
1084 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
1085 return JNI_ERR;
1086
1087 return JNI_OK;
1088 }
1089
1090 /* ============================================================================= */
1091
1092 }
|