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 /* scaffold objects */
37 static jlong timeout = 0;
38
39 /* constant names */
40 #define DEBUGEE_CLASS_NAME "nsk/jvmti/GetObjectsWithTags/objwithtags001"
41 #define OBJECT_CLASS_NAME "nsk/jvmti/GetObjectsWithTags/objwithtags001TestedClass"
42 #define OBJECT_CLASS_SIG "L"OBJECT_CLASS_NAME";"
43 #define OBJECTS_FIELD_NAME "objects"
44 #define OBJECTS_FIELD_SIG "["OBJECT_CLASS_SIG
45
46 /* constants */
47 #define DEFAULT_TAGS_COUNT 4
48 #define DEFAULT_OBJECTS_COUNT 5
49
50 static int tagsCount = 0;
51 static int objectsCount = 0;
52
53 /* 2-dim indexing for flat list */
54 #define ITEM(list, i, j) (((list) + (i * objectsCount))[j])
55
56 /* ============================================================================= */
57
58 /** Obtain tested objects from static field of debugee class. */
getTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int tagsCount,int objectsCount,jobject ** objects,jlong ** tags)59 static int getTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int tagsCount, int objectsCount,
60 jobject* *objects, jlong* *tags) {
61 jclass debugeeClass = NULL;
62 jfieldID objectField = NULL;
63 jobjectArray arrayObject = NULL;
64 int size = tagsCount * objectsCount;
65
66 NSK_DISPLAY2("Allocate memory for lists: %d objects for %d tags\n",
67 objectsCount, tagsCount);
68 if (!NSK_JVMTI_VERIFY(
69 NSK_CPP_STUB3(Allocate, jvmti, (size * sizeof(jobject)),
70 (unsigned char**)objects))) {
71 nsk_jvmti_setFailStatus();
72 return NSK_FALSE;
73 }
74 NSK_DISPLAY1(" ... allocated objects list: 0x%p\n", (void*)objects);
75
76 if (!NSK_JVMTI_VERIFY(
77 NSK_CPP_STUB3(Allocate, jvmti, (tagsCount * sizeof(jlong)),
78 (unsigned char**)tags))) {
79 nsk_jvmti_setFailStatus();
80 return NSK_FALSE;
81 }
82 NSK_DISPLAY1(" ... allocated tags list: 0x%p\n", (void*)tags);
83
84 {
85 int i, k;
86 for (k = 0; k < size; k++) {
87 (*objects)[k] = NULL;
88 }
89
90 for (i = 0; i < tagsCount; i++) {
91 (*tags)[i] = 100 * (jlong)(i + 1);
92 }
93 }
94
95 NSK_DISPLAY1("Find debugee class: %s\n", DEBUGEE_CLASS_NAME);
96 if (!NSK_JNI_VERIFY(jni, (debugeeClass =
97 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) {
98 nsk_jvmti_setFailStatus();
99 return NSK_FALSE;
100 }
101 NSK_DISPLAY1(" ... found class: 0x%p\n", (void*)debugeeClass);
102
103 NSK_DISPLAY1("Find static field: %s\n", OBJECTS_FIELD_NAME);
104 if (!NSK_JNI_VERIFY(jni, (objectField =
105 NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass,
106 OBJECTS_FIELD_NAME, OBJECTS_FIELD_SIG)) != NULL)) {
107 nsk_jvmti_setFailStatus();
108 return NSK_FALSE;
109 }
110 NSK_DISPLAY1(" ... got fieldID: 0x%p\n", (void*)objectField);
111
112 NSK_DISPLAY1("Get objects array from static field: %s\n", OBJECTS_FIELD_NAME);
113 if (!NSK_JNI_VERIFY(jni, (arrayObject = (jobjectArray)
114 NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass,
115 objectField)) != NULL)) {
116 nsk_jvmti_setFailStatus();
117 return NSK_FALSE;
118 }
119 NSK_DISPLAY1(" ... got array object: 0x%p\n", (void*)arrayObject);
120
121 {
122 jsize arrayLen = 0;
123 jsize k;
124
125 if (!NSK_JNI_VERIFY(jni, (arrayLen =
126 NSK_CPP_STUB2(GetArrayLength, jni, arrayObject)) == size)) {
127 NSK_DISPLAY1(" ... got array length: %d\n", (int)size);
128 nsk_jvmti_setFailStatus();
129 return NSK_FALSE;
130 }
131 NSK_DISPLAY1(" ... got array length: %d\n", (int)size);
132
133 for (k = 0; k < size; k++) {
134 jobject object = NULL;
135
136 if (!NSK_JNI_VERIFY(jni, (object =
137 NSK_CPP_STUB3(GetObjectArrayElement, jni, arrayObject, k)) != NULL)) {
138 nsk_jvmti_setFailStatus();
139 return NSK_FALSE;
140 }
141 if (!NSK_JNI_VERIFY(jni, (object =
142 NSK_CPP_STUB2(NewGlobalRef, jni, object)) != NULL)) {
143 nsk_jvmti_setFailStatus();
144 return NSK_FALSE;
145 }
146
147 (*objects)[k] = object;
148 }
149 }
150 NSK_DISPLAY1(" ... object references created: %d objects\n", size);
151
152 return NSK_TRUE;
153 }
154
155 /** Release references to the tested objects and free allocated memory. */
releaseTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int tagsCount,int objectsCount,jobject * objects,jlong * tags)156 static int releaseTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int tagsCount, int objectsCount,
157 jobject *objects, jlong *tags) {
158 int size = tagsCount * objectsCount;
159 int k;
160
161 if (objects == NULL)
162 return NSK_TRUE;
163
164 NSK_DISPLAY1("Release objects references: %d objects\n", size);
165 for (k = 0; k < size; k++) {
166 if (objects[k] != NULL) {
167 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, objects[k]));
168 }
169 }
170 NSK_DISPLAY1(" ... object references released: %d objects\n", size);
171
172 NSK_DISPLAY1("Deallocate objects list: 0x%p\n", (void*)objects);
173 if (!NSK_JVMTI_VERIFY(
174 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)objects))) {
175 nsk_jvmti_setFailStatus();
176 }
177
178 if (tags == NULL)
179 return NSK_FALSE;
180
181 NSK_DISPLAY1("Deallocate tags list: 0x%p\n", (void*)tags);
182 if (!NSK_JVMTI_VERIFY(
183 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)tags))) {
184 nsk_jvmti_setFailStatus();
185 }
186
187 return NSK_TRUE;
188 }
189
190 /** Get and check tagged objects. */
checkTestedObjects(jvmtiEnv * jvmti,JNIEnv * jni,int tagsCount,int objectsCount,jlong tags[],jobject objects[],const char kind[],int expectedCount)191 static int checkTestedObjects(jvmtiEnv* jvmti, JNIEnv* jni, int tagsCount, int objectsCount,
192 jlong tags[], jobject objects[],
193 const char kind[], int expectedCount) {
194 jint taggedObjectsCount = 0;
195 jobject* taggedObjectsList = NULL;
196 jlong* taggedObjectsTags = NULL;
197 jlong expectedTag = 0;
198 int k;
199
200 NSK_DISPLAY1("Get tagged objects: %d tags\n", tagsCount);
201 if (!NSK_JVMTI_VERIFY(
202 NSK_CPP_STUB6(GetObjectsWithTags, jvmti, tagsCount, tags,
203 &taggedObjectsCount, &taggedObjectsList, &taggedObjectsTags))) {
204 nsk_jvmti_setFailStatus();
205 return NSK_TRUE;
206 }
207 NSK_DISPLAY1(" ... got tagged objects: %d\n", (int)taggedObjectsCount);
208
209 if (taggedObjectsCount != expectedCount) {
210 NSK_COMPLAIN3("GetObjectsWithTags() returns unexpected number of objects %s:\n"
211 "# got objects: %d\n"
212 "# expected: %d\n",
213 kind, (int)taggedObjectsCount, (int)expectedCount);
214 nsk_jvmti_setFailStatus();
215 }
216
217 if (taggedObjectsList == NULL && taggedObjectsCount > 0) {
218 NSK_COMPLAIN2("GetObjectsWithTags() returns NULL list of objects %s: 0x%p\n",
219 kind, (void*)taggedObjectsList);
220 nsk_jvmti_setFailStatus();
221 return NSK_TRUE;
222 }
223
224 if (taggedObjectsTags == NULL && taggedObjectsCount > 0) {
225 NSK_COMPLAIN2("GetObjectsWithTags() returns NULL list of tags for objects %s: 0x%p\n",
226 kind, (void*)taggedObjectsTags);
227 nsk_jvmti_setFailStatus();
228 return NSK_TRUE;
229 }
230
231 for (k = 0; k < taggedObjectsCount; k++) {
232 jobject object = taggedObjectsList[k];
233 jlong tag = taggedObjectsTags[k];
234 int objectsFound = 0;
235 int i, j, l;
236
237 NSK_DISPLAY3(" #%d: object: 0x%p, tag: %ld\n", k, (void*)object, (long)tag);
238
239 if (object == NULL) {
240 NSK_COMPLAIN3("GetObjectsWithTags() returns NULL for object #%d %s: 0x%p\n",
241 k, kind, (void*)object);
242 nsk_jvmti_setFailStatus();
243 continue;
244 }
245
246 objectsFound = 0;
247 for (l = k + 1; l < taggedObjectsCount; l++) {
248 if (object == taggedObjectsList[l])
249 objectsFound++;
250 }
251 if (objectsFound > 0) {
252 NSK_COMPLAIN4("GetObjectsWithTags() returns %d duplicates for object #%d %s: 0x%p\n",
253 objectsFound, k, kind, (void*)object);
254 nsk_jvmti_setFailStatus();
255 continue;
256 }
257
258 objectsFound = 0;
259 for (i = 0; i < tagsCount; i++) {
260 for (j = 0; j < objectsCount; j++) {
261 jobject foundObject = ITEM(objects, i, j);
262
263 if (NSK_CPP_STUB3(IsSameObject, jni, object, foundObject)) {
264 objectsFound++;
265
266 if (expectedCount > 0)
267 expectedTag = tags[i];
268
269 if (tag != expectedTag) {
270 NSK_COMPLAIN6("GetObjectsWithTags() returns wrong tag for object #%d %s:\n"
271 "# got object: 0x%p\n"
272 "# original: 0x%p\n"
273 "# got tag: %ld\n"
274 "# original: %ld\n",
275 k, kind,
276 (void*)object, (void*)foundObject,
277 (long)tag, (long)expectedTag);
278 nsk_jvmti_setFailStatus();
279 }
280 break;
281 }
282 }
283
284 if (objectsFound > 0)
285 break;
286 }
287
288 if (objectsFound <= 0) {
289 NSK_COMPLAIN4("GetObjectsWithTags() returns unexpected #%d object %s:\n"
290 "# got object: 0x%p\n"
291 "# got tag: %ld\n",
292 k, kind,
293 (void*)object, (long)tag);
294 nsk_jvmti_setFailStatus();
295 }
296 }
297
298 NSK_DISPLAY1("Deallocate got objects list: 0x%p\n", (void*)taggedObjectsList);
299 if (!NSK_JVMTI_VERIFY(
300 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)taggedObjectsList))) {
301 nsk_jvmti_setFailStatus();
302 }
303 NSK_DISPLAY1("Deallocate got tags list: 0x%p\n", (void*)taggedObjectsTags);
304 if (!NSK_JVMTI_VERIFY(
305 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)taggedObjectsTags))) {
306 nsk_jvmti_setFailStatus();
307 }
308
309 return NSK_TRUE;
310 }
311
312 /** Agent algorithm. */
313 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * jni,void * arg)314 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
315 NSK_DISPLAY0("Wait for objects created\n");
316 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
317 return;
318
319 /* perform testing */
320 {
321 int size = tagsCount * objectsCount;
322 jobject* objects = NULL;
323 jlong* tags = NULL;
324
325 NSK_DISPLAY0(">>> Obtain tested objects list from a static field of debugee class\n");
326 {
327 if (!NSK_VERIFY(getTestedObjects(jvmti, jni, tagsCount, objectsCount,
328 &objects, &tags)))
329 return;
330 }
331
332 NSK_DISPLAY0(">>> Tagging tested objects with different tags\n");
333 {
334 int i, j;
335
336 for (i = 0; i < tagsCount; i++) {
337 NSK_DISPLAY2(" tagging with %ld: %d objects\n", (long)tags[i], objectsCount);
338 for (j = 0; j < objectsCount; j++) {
339 jobject object = ITEM(objects, i, j);
340
341 NSK_DISPLAY3(" #%d: object: 0x%p, tag: %ld\n",
342 j, (void*)object, (long)tags[i]);
343 if (!NSK_JVMTI_VERIFY(
344 NSK_CPP_STUB3(SetTag, jvmti, object, tags[i]))) {
345 nsk_jvmti_setFailStatus();
346 return;
347 }
348 }
349 }
350 NSK_DISPLAY1(" ... objects tagged: %d objects\n", (tagsCount * objectsCount));
351 }
352
353 NSK_DISPLAY0(">>> Testcase #1: get tagged objects before objects data changed\n");
354 {
355 if (!NSK_VERIFY(
356 checkTestedObjects(jvmti, jni, tagsCount, objectsCount,
357 tags, objects, "before changed", size)))
358 return;
359 }
360
361 NSK_DISPLAY0(">>> Let debugee to change object data\n");
362 {
363 if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
364 return;
365 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
366 return;
367 }
368
369 NSK_DISPLAY0(">>> Testcase #2: get tagged objects after objects data are changed\n");
370 {
371 if (!NSK_VERIFY(
372 checkTestedObjects(jvmti, jni, tagsCount, objectsCount,
373 tags, objects, "after changed", size)))
374 return;
375 }
376
377 NSK_DISPLAY0(">>> Untagging all tested objects (i.e., tagging with zero tag)\n");
378 {
379 jlong tag = 0;
380 int i, j;
381
382 for (i = 0; i < tagsCount; i++) {
383 NSK_DISPLAY2(" tagging with %ld: %d objects\n", (long)tag, objectsCount);
384 for (j = 0; j < objectsCount; j++) {
385 jobject object = ITEM(objects, i , j);
386
387 NSK_DISPLAY3(" #%d: object: 0x%p, tag: %ld\n",
388 j, (void*)object, (long)tag);
389 if (!NSK_JVMTI_VERIFY(
390 NSK_CPP_STUB3(SetTag, jvmti, object, tag))) {
391 nsk_jvmti_setFailStatus();
392 return;
393 }
394 }
395 }
396 NSK_DISPLAY1(" ... objects untagged: %d objects\n", (tagsCount * objectsCount));
397 }
398
399 NSK_DISPLAY0(">>> Testcase #3: get tagged objects after objects untagged\n");
400 {
401 if (!NSK_VERIFY(
402 checkTestedObjects(jvmti, jni, tagsCount, objectsCount,
403 tags, objects, "after untagged", 0)))
404 return;
405 }
406
407 NSK_DISPLAY0(">>> Clean used data\n");
408 {
409 if (!NSK_VERIFY(releaseTestedObjects(jvmti, jni, tagsCount, objectsCount,
410 objects, tags)))
411 return;
412 }
413 }
414
415 NSK_DISPLAY0("Let debugee to finish\n");
416 if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
417 return;
418 }
419
420 /* ============================================================================= */
421
422 /** Agent library initialization. */
423 #ifdef STATIC_BUILD
Agent_OnLoad_objwithtags001(JavaVM * jvm,char * options,void * reserved)424 JNIEXPORT jint JNICALL Agent_OnLoad_objwithtags001(JavaVM *jvm, char *options, void *reserved) {
425 return Agent_Initialize(jvm, options, reserved);
426 }
Agent_OnAttach_objwithtags001(JavaVM * jvm,char * options,void * reserved)427 JNIEXPORT jint JNICALL Agent_OnAttach_objwithtags001(JavaVM *jvm, char *options, void *reserved) {
428 return Agent_Initialize(jvm, options, reserved);
429 }
JNI_OnLoad_objwithtags001(JavaVM * jvm,char * options,void * reserved)430 JNIEXPORT jint JNI_OnLoad_objwithtags001(JavaVM *jvm, char *options, void *reserved) {
431 return JNI_VERSION_1_8;
432 }
433 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)434 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
435 jvmtiEnv* jvmti = NULL;
436
437 /* init framework and parse options */
438 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
439 return JNI_ERR;
440
441 timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
442
443 /* get option values */
444 tagsCount = nsk_jvmti_findOptionIntValue("tags", DEFAULT_TAGS_COUNT);
445 objectsCount = nsk_jvmti_findOptionIntValue("objects", DEFAULT_OBJECTS_COUNT);
446 if (!NSK_VERIFY(tagsCount > 0 && objectsCount > 0))
447 return JNI_ERR;
448
449 /* create JVMTI environment */
450 if (!NSK_VERIFY((jvmti =
451 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
452 return JNI_ERR;
453
454 /* add required capabilities */
455 {
456 jvmtiCapabilities caps;
457
458 memset(&caps, 0, sizeof(caps));
459 caps.can_tag_objects = 1;
460 if (!NSK_JVMTI_VERIFY(
461 NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) {
462 return JNI_ERR;
463 }
464 }
465
466 /* register agent proc and arg */
467 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
468 return JNI_ERR;
469
470 return JNI_OK;
471 }
472
473 /* ============================================================================= */
474
475 #ifdef __cplusplus
476 }
477 #endif
478