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 <stdio.h>
25 #include <stdlib.h>
26 #include "jvmti.h"
27 #include "agent_common.h"
28 #include <jvmti_tools.h>
29 #include "JVMTITools.h"
30
31 extern "C" {
32
33 // Deallocate memory region allocated by VM
34 #define DEALLOCATE(p) \
35 if (p != NULL) \
36 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate(p))) \
37 { \
38 NSK_COMPLAIN0("Failed to deallocate: ##p##\n"); \
39 }
40
41 static jvmtiEnv *jvmti;
42 static jvmtiCapabilities caps;
43 static jvmtiEventCallbacks callbacks;
44 static int watch_jvmti_events = 0; /* ignore JVMTI events by default */
45 static volatile int number_of_generated_events = 0; /* number of generated events */
46 static jboolean result = JNI_TRUE; /* total result of the test */
47
48 static jrawMonitorID watch_ev_monitor;
49
set_watch_jvmti_events(int value)50 static void set_watch_jvmti_events(int value) {
51 jvmti->RawMonitorEnter(watch_ev_monitor);
52
53 watch_jvmti_events = value;
54
55 jvmti->RawMonitorExit(watch_ev_monitor);
56 }
57
58 void JNICALL
FramePop(jvmtiEnv * jvmti_env,JNIEnv * env,jthread thread,jmethodID method,jboolean wasPopedByException)59 FramePop(
60 jvmtiEnv *jvmti_env
61 , JNIEnv *env
62 , jthread thread
63 , jmethodID method
64 , jboolean wasPopedByException
65 )
66 {
67 jvmti->RawMonitorEnter(watch_ev_monitor);
68
69 if (watch_jvmti_events) {
70 NSK_COMPLAIN1("#### FramePop event occurred (%d) ####\n", method);
71 number_of_generated_events++;
72 }
73
74 jvmti->RawMonitorExit(watch_ev_monitor);
75 }
76
77 void JNICALL
MethodExit(jvmtiEnv * jvmti_env,JNIEnv * env,jthread thread,jmethodID method,jboolean was_poped_by_exc,jvalue return_value)78 MethodExit(
79 jvmtiEnv *jvmti_env
80 , JNIEnv *env
81 , jthread thread
82 , jmethodID method
83 , jboolean was_poped_by_exc
84 , jvalue return_value
85 )
86 {
87 jvmti->RawMonitorEnter(watch_ev_monitor);
88
89 if (watch_jvmti_events) {
90 jvmtiThreadInfo thr_info;
91 char *class_signature;
92 char *entry_name;
93 char *entry_sig;
94 jclass klass;
95
96 int failure = 1;
97
98 do {
99 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(thread, &thr_info)))
100 {
101 break;
102 }
103
104 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodDeclaringClass(method, &klass)))
105 {
106 break;
107 }
108
109 if (!NSK_JVMTI_VERIFY(jvmti->GetClassSignature(klass, &class_signature, NULL)))
110 {
111 break;
112 }
113
114 if (!NSK_JVMTI_VERIFY(jvmti->GetMethodName(method, &entry_name, &entry_sig, NULL)))
115 {
116 break;
117 }
118
119 failure = 0;
120 NSK_COMPLAIN5("#### MethodExit event occurred: (tid: %d), thread: %s, %s %s %s\n"
121 , thread
122 , thr_info.name == NULL ? "<Unnamed>" : thr_info.name
123 , class_signature
124 , entry_name
125 , entry_sig
126 );
127 } while (0);
128
129 if (failure) {
130 NSK_COMPLAIN1("#### MethodExit event occurred (tid: %d) ####\n"
131 , thread
132 );
133 }
134
135 DEALLOCATE((unsigned char *)class_signature);
136 DEALLOCATE((unsigned char *)entry_name);
137 DEALLOCATE((unsigned char *)entry_sig);
138
139 number_of_generated_events++;
140 }
141
142 jvmti->RawMonitorExit(watch_ev_monitor);
143 }
144
suspendThread(jobject suspendedThread)145 jboolean suspendThread(jobject suspendedThread) {
146 if (!caps.can_pop_frame || !caps.can_suspend) {
147 return JNI_TRUE;
148 }
149
150 NSK_DISPLAY0(">>>>>>>> Invoke SuspendThread()\n");
151
152 if (!NSK_JVMTI_VERIFY(jvmti->SuspendThread(suspendedThread)))
153 {
154 return JNI_FALSE;
155 }
156
157 NSK_DISPLAY0("<<<<<<<< SuspendThread() is successfully done\n");
158
159 return JNI_TRUE;
160 }
161
resThread(jobject suspendedThread)162 jboolean resThread(jobject suspendedThread) {
163 if (!caps.can_pop_frame || !caps.can_suspend) {
164 return JNI_TRUE;
165 }
166
167 NSK_DISPLAY0(">>>>>>>> Invoke ResumeThread()\n");
168
169 if (!NSK_JVMTI_VERIFY(jvmti->ResumeThread(suspendedThread)))
170 {
171 return JNI_FALSE;
172 }
173
174 NSK_DISPLAY0("<<<<<<<< ResumeThread() is successfully done\n");
175
176 return JNI_TRUE;
177 }
178
179 JNIEXPORT jboolean JNICALL
Java_nsk_jvmti_PopFrame_popframe005_doPopFrame(JNIEnv * env,jclass klass,jobject frameThr)180 Java_nsk_jvmti_PopFrame_popframe005_doPopFrame(
181 JNIEnv *env
182 , jclass klass
183 , jobject frameThr
184 )
185 {
186 if (!caps.can_pop_frame || !caps.can_suspend) {
187 return JNI_TRUE;
188 }
189
190 if (suspendThread(frameThr) != JNI_TRUE) {
191 return JNI_FALSE;
192 }
193
194 if (!NSK_JVMTI_VERIFY(
195 jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_EXIT, frameThr)))
196 {
197 result = JNI_FALSE;
198 }
199
200 if (!NSK_JVMTI_VERIFY(
201 jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_FRAME_POP, frameThr)))
202 {
203 result = JNI_FALSE;
204 }
205
206 NSK_DISPLAY0(">>>>>>>> Invoke PopFrame()\n");
207
208 set_watch_jvmti_events(1); /* watch JVMTI events */
209
210 if (!NSK_JVMTI_VERIFY(jvmti->PopFrame(frameThr)))
211 {
212 result = JNI_FALSE;
213 } else {
214 NSK_DISPLAY0("Check #1 PASSED: PopFrame() is successfully done\n");
215 }
216
217 set_watch_jvmti_events(0); /* ignore again JVMTI events */
218
219 if (number_of_generated_events) {
220 NSK_COMPLAIN1("%d JVMTI events have been generated by the function PopFrame()\n"
221 , number_of_generated_events
222 );
223 result = JNI_FALSE;
224 } else {
225 NSK_DISPLAY0("Check #2 PASSED: No JVMTI events have been generated by the function PopFrame()\n");
226 }
227
228 if (resThread(frameThr) != JNI_TRUE)
229 return JNI_FALSE;
230
231 return result;
232 }
233
234 #ifdef STATIC_BUILD
Agent_OnLoad_popframe005(JavaVM * jvm,char * options,void * reserved)235 JNIEXPORT jint JNICALL Agent_OnLoad_popframe005(JavaVM *jvm, char *options, void *reserved) {
236 return Agent_Initialize(jvm, options, reserved);
237 }
Agent_OnAttach_popframe005(JavaVM * jvm,char * options,void * reserved)238 JNIEXPORT jint JNICALL Agent_OnAttach_popframe005(JavaVM *jvm, char *options, void *reserved) {
239 return Agent_Initialize(jvm, options, reserved);
240 }
JNI_OnLoad_popframe005(JavaVM * jvm,char * options,void * reserved)241 JNIEXPORT jint JNI_OnLoad_popframe005(JavaVM *jvm, char *options, void *reserved) {
242 return JNI_VERSION_1_8;
243 }
244 #endif
Agent_Initialize(JavaVM * vm,char * options,void * reserved)245 jint Agent_Initialize(JavaVM *vm, char *options, void *reserved)
246 {
247 jvmtiError err;
248
249 if (!NSK_VERIFY(
250 nsk_jvmti_parseOptions(options)
251 ))
252 {
253 return JNI_ERR;
254 }
255
256 if (!NSK_VERIFY(
257 (jvmti = nsk_jvmti_createJVMTIEnv(vm, reserved)) != NULL
258 ))
259 {
260 return JNI_ERR;
261 }
262
263 if (!NSK_JVMTI_VERIFY(jvmti->GetPotentialCapabilities(&caps)))
264 {
265 return JNI_ERR;
266 }
267
268 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
269 {
270 return JNI_ERR;
271 }
272
273 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
274 {
275 return JNI_ERR;
276 }
277
278 if (!caps.can_pop_frame) {
279 NSK_COMPLAIN0("Warning: PopFrame is not implemented\n");
280 return JNI_OK;
281 }
282
283 if (!caps.can_suspend) {
284 NSK_COMPLAIN0("Warning: suspend/resume is not implemented\n");
285 return JNI_OK;
286 }
287
288 if (caps.can_generate_frame_pop_events
289 && caps.can_generate_method_exit_events)
290 {
291 callbacks.MethodExit = &MethodExit;
292 callbacks.FramePop = &FramePop;
293
294 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)
295 )))
296 {
297 return JNI_ERR;
298 }
299 } else {
300 NSK_COMPLAIN0("Warning: FramePop or MethodExit event is not implemented\n");
301 }
302
303 err = jvmti->CreateRawMonitor("watch_ev_monitor", &watch_ev_monitor);
304 if (err != JVMTI_ERROR_NONE) {
305 printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
306 TranslateError(err), err);
307 return JNI_ERR;
308 }
309
310 return JNI_OK;
311 }
312
313 }
314