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