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