1 /*
2  * Copyright (c) 2004, 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 static jlong timeout = 0;
35 
36 static long objCounter = 0;
37 static int userData = 0;
38 static jvmtiEnv* st_jvmti = NULL;
39 
40 /* ============================================================================= */
41 
42 /* ============================================================================= */
43 
44 
45 /* jvmtiHeapRootCallback */
46 jvmtiIterationControl JNICALL
heapRootCallback(jvmtiHeapRootKind root_kind,jlong class_tag,jlong size,jlong * tag_ptr,void * user_data)47 heapRootCallback(jvmtiHeapRootKind root_kind,
48                  jlong class_tag,
49                  jlong size,
50                  jlong* tag_ptr,
51                  void* user_data) {
52 
53     jrawMonitorID monitor_ptr = NULL;
54 
55     *tag_ptr = (jlong)++objCounter;
56 
57     if (!NSK_JVMTI_VERIFY(st_jvmti->CreateRawMonitor("heapRootMonitor", &monitor_ptr))) {
58         nsk_jvmti_setFailStatus();
59         return JVMTI_ITERATION_ABORT;
60     }
61 
62     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorEnter(monitor_ptr))) {
63         nsk_jvmti_setFailStatus();
64         return JVMTI_ITERATION_ABORT;
65     }
66 
67     /* Enter second time */
68     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorEnter(monitor_ptr))) {
69         nsk_jvmti_setFailStatus();
70         return JVMTI_ITERATION_ABORT;
71     }
72 
73     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorWait(monitor_ptr, (jlong)1))) {
74         nsk_jvmti_setFailStatus();
75     }
76 
77     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorNotify(monitor_ptr))) {
78         nsk_jvmti_setFailStatus();
79     }
80 
81     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorNotifyAll(monitor_ptr))) {
82         nsk_jvmti_setFailStatus();
83     }
84 
85     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorExit(monitor_ptr))) {
86         nsk_jvmti_setFailStatus();
87         return JVMTI_ITERATION_ABORT;
88     }
89 
90     /* Exit second time */
91     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorExit(monitor_ptr))) {
92         nsk_jvmti_setFailStatus();
93         return JVMTI_ITERATION_ABORT;
94     }
95 
96     if (!NSK_JVMTI_VERIFY(st_jvmti->DestroyRawMonitor(monitor_ptr))) {
97         nsk_jvmti_setFailStatus();
98     }
99 /*
100     NSK_DISPLAY1("heapRootCallback: %d\n", objCounter);
101 */
102     return JVMTI_ITERATION_CONTINUE;
103 }
104 
105 /* jvmtiStackReferenceCallback */
106 jvmtiIterationControl JNICALL
stackReferenceCallback(jvmtiHeapRootKind root_kind,jlong class_tag,jlong size,jlong * tag_ptr,jlong thread_tag,jint depth,jmethodID method,jint slot,void * user_data)107 stackReferenceCallback(jvmtiHeapRootKind root_kind,
108                        jlong     class_tag,
109                        jlong     size,
110                        jlong*    tag_ptr,
111                        jlong     thread_tag,
112                        jint      depth,
113                        jmethodID method,
114                        jint      slot,
115                        void*     user_data) {
116 
117     jrawMonitorID monitor_ptr = NULL;
118 
119     *tag_ptr = (jlong)++objCounter;
120 
121     if (!NSK_JVMTI_VERIFY(st_jvmti->CreateRawMonitor("stackRefMonitor", &monitor_ptr))) {
122         nsk_jvmti_setFailStatus();
123         return JVMTI_ITERATION_ABORT;
124     }
125 
126     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorEnter(monitor_ptr))) {
127         nsk_jvmti_setFailStatus();
128         return JVMTI_ITERATION_ABORT;
129     }
130 
131     /* Enter second time */
132     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorEnter(monitor_ptr))) {
133         nsk_jvmti_setFailStatus();
134         return JVMTI_ITERATION_ABORT;
135     }
136 
137     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorWait(monitor_ptr, (jlong)1))) {
138         nsk_jvmti_setFailStatus();
139     }
140 
141     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorNotify(monitor_ptr))) {
142         nsk_jvmti_setFailStatus();
143     }
144 
145     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorNotifyAll(monitor_ptr))) {
146         nsk_jvmti_setFailStatus();
147     }
148 
149     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorExit(monitor_ptr))) {
150         nsk_jvmti_setFailStatus();
151         return JVMTI_ITERATION_ABORT;
152     }
153 
154     /* Exit second time */
155     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorExit(monitor_ptr))) {
156         nsk_jvmti_setFailStatus();
157         return JVMTI_ITERATION_ABORT;
158     }
159 
160     if (!NSK_JVMTI_VERIFY(st_jvmti->DestroyRawMonitor(monitor_ptr))) {
161         nsk_jvmti_setFailStatus();
162     }
163 /*
164     NSK_DISPLAY1("stackRefenceCallback: %d\n", objCounter);
165 */
166     return JVMTI_ITERATION_CONTINUE;
167 }
168 
169 
170 /* jvmtiObjectReferenceCallback */
171 jvmtiIterationControl JNICALL
objectReferenceCallback(jvmtiObjectReferenceKind reference_kind,jlong class_tag,jlong size,jlong * tag_ptr,jlong referrer_tag,jint referrer_index,void * user_data)172 objectReferenceCallback(jvmtiObjectReferenceKind reference_kind,
173                         jlong  class_tag,
174                         jlong  size,
175                         jlong* tag_ptr,
176                         jlong  referrer_tag,
177                         jint   referrer_index,
178                         void*  user_data) {
179 
180     jrawMonitorID monitor_ptr = NULL;
181 
182     *tag_ptr = (jlong)++objCounter;
183 
184     if (!NSK_JVMTI_VERIFY(st_jvmti->CreateRawMonitor("objRefMonitor", &monitor_ptr))) {
185         nsk_jvmti_setFailStatus();
186         return JVMTI_ITERATION_ABORT;
187     }
188 
189     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorEnter(monitor_ptr))) {
190         nsk_jvmti_setFailStatus();
191         return JVMTI_ITERATION_ABORT;
192     }
193 
194     /* Enter second time */
195     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorEnter(monitor_ptr))) {
196         nsk_jvmti_setFailStatus();
197         return JVMTI_ITERATION_ABORT;
198     }
199 
200     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorWait(monitor_ptr, (jlong)1))) {
201         nsk_jvmti_setFailStatus();
202     }
203 
204     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorNotify(monitor_ptr))) {
205         nsk_jvmti_setFailStatus();
206     }
207 
208     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorNotifyAll(monitor_ptr))) {
209         nsk_jvmti_setFailStatus();
210     }
211 
212     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorExit(monitor_ptr))) {
213         nsk_jvmti_setFailStatus();
214         return JVMTI_ITERATION_ABORT;
215     }
216 
217     /* Exit second time */
218     if (!NSK_JVMTI_VERIFY(st_jvmti->RawMonitorExit(monitor_ptr))) {
219         nsk_jvmti_setFailStatus();
220         return JVMTI_ITERATION_ABORT;
221     }
222 
223     if (!NSK_JVMTI_VERIFY(st_jvmti->DestroyRawMonitor(monitor_ptr))) {
224         nsk_jvmti_setFailStatus();
225     }
226 
227     NSK_DISPLAY1("objectRefenceCallback: %d\n", objCounter);
228     return JVMTI_ITERATION_ABORT;
229 }
230 
231 /* ============================================================================= */
232 
233 /** Agent algorithm. */
234 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * jni,void * arg)235 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
236 
237     NSK_DISPLAY0("Wait for debugee start\n");
238     if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
239         return;
240 
241     {
242         do {
243             NSK_DISPLAY0("Calling IterateOverReachableObjects\n");
244             {
245                 if (!NSK_JVMTI_VERIFY(
246                         jvmti->IterateOverReachableObjects(heapRootCallback,
247                                                            stackReferenceCallback,
248                                                            objectReferenceCallback,
249                                                            &userData))) {
250                     nsk_jvmti_setFailStatus();
251                     break;
252                 }
253             }
254 
255             if (objCounter == 0) {
256                 NSK_COMPLAIN0("IterateOverReachableObjects call had not visited any object\n");
257                 nsk_jvmti_setFailStatus();
258                 break;
259             } else {
260                 NSK_DISPLAY1("Number of objects the IterateOverReachableObjects visited: %d\n", objCounter);
261             }
262 
263         } while (0);
264     }
265 
266     NSK_DISPLAY0("Let debugee to finish\n");
267     if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
268         return;
269 }
270 
271 /* ============================================================================= */
272 
273 /* ============================================================================= */
274 
275 /** Agent library initialization. */
276 #ifdef STATIC_BUILD
Agent_OnLoad_iterreachobj003(JavaVM * jvm,char * options,void * reserved)277 JNIEXPORT jint JNICALL Agent_OnLoad_iterreachobj003(JavaVM *jvm, char *options, void *reserved) {
278     return Agent_Initialize(jvm, options, reserved);
279 }
Agent_OnAttach_iterreachobj003(JavaVM * jvm,char * options,void * reserved)280 JNIEXPORT jint JNICALL Agent_OnAttach_iterreachobj003(JavaVM *jvm, char *options, void *reserved) {
281     return Agent_Initialize(jvm, options, reserved);
282 }
JNI_OnLoad_iterreachobj003(JavaVM * jvm,char * options,void * reserved)283 JNIEXPORT jint JNI_OnLoad_iterreachobj003(JavaVM *jvm, char *options, void *reserved) {
284     return JNI_VERSION_1_8;
285 }
286 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)287 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
288     jvmtiEnv* jvmti = NULL;
289 
290     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
291         return JNI_ERR;
292 
293     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
294 
295     if (!NSK_VERIFY((jvmti =
296             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
297         return JNI_ERR;
298 
299     /* save pointer to environment to use it in callbacks */
300     st_jvmti = jvmti;
301 
302     {
303         jvmtiCapabilities caps;
304 
305         memset(&caps, 0, sizeof(caps));
306         caps.can_tag_objects = 1;
307         if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
308             return JNI_ERR;
309         }
310     }
311 
312     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
313         return JNI_ERR;
314 
315     return JNI_OK;
316 }
317 
318 /* ============================================================================= */
319 
320 }
321