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 <stdio.h>
25 #include <string.h>
26 #include <jvmti.h>
27 #include "agent_common.h"
28
29 #include "nsk_tools.h"
30 #include "JVMTITools.h"
31 #include "jvmti_tools.h"
32
33 extern "C" {
34
35 #define STATUS_FAILED 2
36 #define PASSED 0
37
38 #define MAX_SIZE 256
39
40 static jvmtiEnv *jvmti = NULL;
41 static jvmtiEventCallbacks callbacks;
42 static jvmtiCapabilities caps;
43
44 static volatile int gcfinish = 0, gcstart = 0, objfree = 0;
45 static long objectCount = 0;
46
47 static jlong nanos = 0;
48 static jlong timeout = 0;
49 static jvmtiTimerInfo timer_info1, timer_info2;
50 static int user_data = 0;
51
52 typedef struct _LocalStorage {
53 unsigned char data[MAX_SIZE];
54 } LocalStorage;
55
56 static LocalStorage stor;
57
envStorageFunc(jvmtiEnv * jvmti_env,const char * msg)58 static void envStorageFunc(jvmtiEnv *jvmti_env, const char *msg) {
59 LocalStorage* obtainedData = NULL;
60 LocalStorage* storedData = &stor;
61
62 NSK_DISPLAY2("%s: setting an environment local storage 0x%p ...\n",
63 msg, (void*) &stor);
64 if (!NSK_JVMTI_VERIFY(jvmti_env->SetEnvironmentLocalStorage((const void*) &stor))) {
65 nsk_jvmti_setFailStatus();
66 NSK_COMPLAIN1("%s: unable to set an environment local storage\n\n",
67 msg);
68 return;
69 }
70
71 NSK_DISPLAY1("%s: getting an environment local storage ...\n",
72 msg);
73 if (!NSK_JVMTI_VERIFY(jvmti_env->GetEnvironmentLocalStorage((void**) &obtainedData))) {
74 nsk_jvmti_setFailStatus();
75 NSK_COMPLAIN1("%s: unable to get an environment local storage\n\n",
76 msg);
77 return;
78 }
79 else {
80 if (obtainedData != storedData) {
81 nsk_jvmti_setFailStatus();
82 NSK_COMPLAIN3(
83 "%s: obtained an environment local storage has unexpected pointer:\n"
84 "got: 0x%p\texpected: 0x%p\n\n",
85 msg, (void*) obtainedData, (void*) storedData);
86 }
87 }
88 }
89
timerFunc(jvmtiEnv * jvmti_env,const char * msg)90 static void timerFunc(jvmtiEnv *jvmti_env, const char *msg) {
91 if (!NSK_JVMTI_VERIFY(jvmti_env->GetCurrentThreadCpuTimerInfo(&timer_info1))) {
92 nsk_jvmti_setFailStatus();
93 NSK_COMPLAIN1("%s: GetCurrentThreadCpuTimerInfo returned unexpected error code\n\n",
94 msg);
95 }
96 /* Check the returned jvmtiTimerInfo structure */
97 if (timer_info1.max_value == 0) {
98 nsk_jvmti_setFailStatus();
99 NSK_COMPLAIN1("%s: GetCurrentThreadCpuTimerInfo returned zero in jvmtiTimerInfo.max_value\n\n",
100 msg);
101 }
102 if (timer_info1.may_skip_forward != JNI_TRUE && timer_info1.may_skip_forward != JNI_FALSE) {
103 nsk_jvmti_setFailStatus();
104 NSK_COMPLAIN1("%s: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n\n",
105 msg);
106 }
107 if (timer_info1.may_skip_backward != JNI_TRUE && timer_info1.may_skip_backward != JNI_FALSE) {
108 nsk_jvmti_setFailStatus();
109 NSK_COMPLAIN1("%s: GetCurrentThreadCpuTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n\n",
110 msg);
111 }
112 /* ---------------------------------------------------------------------- */
113
114 if (!NSK_JVMTI_VERIFY(jvmti_env->GetCurrentThreadCpuTime(&nanos))) {
115 nsk_jvmti_setFailStatus();
116 NSK_COMPLAIN1("%s: GetCurrentThreadCpuTime returned unexpected error code\n\n",
117 msg);
118 }
119 /* ---------------------------------------------------------------------- */
120
121
122 if (!NSK_JVMTI_VERIFY(jvmti_env->GetTimerInfo(&timer_info2))) {
123 nsk_jvmti_setFailStatus();
124 NSK_COMPLAIN1("%s: GetTimerInfo returned unexpected error code\n\n",
125 msg);
126 }
127 /* Check the returned jvmtiTimerInfo structure */
128 if (timer_info2.max_value == 0) {
129 nsk_jvmti_setFailStatus();
130 NSK_COMPLAIN1("%s: GetTimerInfo returned zero in jvmtiTimerInfo.max_value\n\n",
131 msg);
132 }
133 if (timer_info2.may_skip_forward != JNI_TRUE && timer_info2.may_skip_forward != JNI_FALSE) {
134 nsk_jvmti_setFailStatus();
135 NSK_COMPLAIN1("%s: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_forward\n\n",
136 msg);
137 }
138 if (timer_info2.may_skip_backward != JNI_TRUE && timer_info2.may_skip_backward != JNI_FALSE) {
139 nsk_jvmti_setFailStatus();
140 NSK_COMPLAIN1("%s: GetTimerInfo returned unknown type value in jvmtiTimerInfo.may_skip_backward\n\n",
141 msg);
142 }
143 /* ---------------------------------------------------------------------- */
144
145 nanos = 0;
146 if (!NSK_JVMTI_VERIFY(jvmti_env->GetTime(&nanos))) {
147 nsk_jvmti_setFailStatus();
148 NSK_COMPLAIN1("%s: GetTime returned unexpected error code\n\n",
149 msg);
150 }
151
152 }
153
154 /** callback functions **/
155 void JNICALL
GarbageCollectionFinish(jvmtiEnv * jvmti_env)156 GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
157 gcfinish++;
158 NSK_DISPLAY1(">>>> GarbageCollectionFinish event #%d received\n",
159 gcfinish);
160
161 timerFunc(jvmti_env, "GarbageCollectionFinish");
162
163 envStorageFunc(jvmti_env, "GarbageCollectionFinish");
164
165 NSK_DISPLAY0("<<<<\n\n");
166 }
167
168 void JNICALL
GarbageCollectionStart(jvmtiEnv * jvmti_env)169 GarbageCollectionStart(jvmtiEnv *jvmti_env) {
170 gcstart++;
171 NSK_DISPLAY1(">>>> GarbageCollectionStart event #%d received\n",
172 gcstart);
173
174 timerFunc(jvmti_env, "GarbageCollectionStart");
175
176 envStorageFunc(jvmti_env, "GarbageCollectionStart");
177
178 NSK_DISPLAY0("<<<<\n\n");
179 }
180
181 void JNICALL
ObjectFree(jvmtiEnv * jvmti_env,jlong tag)182 ObjectFree(jvmtiEnv *jvmti_env, jlong tag) {
183 NSK_DISPLAY0(">>>> ObjectFree event received\n");
184 objfree++;
185
186 timerFunc(jvmti_env, "ObjectFree");
187
188 envStorageFunc(jvmti_env, "ObjectFree");
189
190 NSK_DISPLAY0("<<<<\n\n");
191 }
192
193 jvmtiIterationControl JNICALL
heapObjectCallback(jlong class_tag,jlong size,jlong * tag_ptr,void * user_data)194 heapObjectCallback(jlong class_tag,
195 jlong size,
196 jlong* tag_ptr,
197 void* user_data) {
198
199 /* set tag */
200 *tag_ptr = (jlong)++objectCount;
201
202 /* iterate over only first MAX_SIZE objects */
203 if (objectCount >= MAX_SIZE)
204 return JVMTI_ITERATION_ABORT;
205
206 return JVMTI_ITERATION_CONTINUE;
207 }
208
209 /************************/
210
211 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * jni,void * arg)212 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) {
213
214 NSK_DISPLAY0("Wait for debugee start\n\n");
215 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
216 return;
217
218 NSK_DISPLAY0("Call IterateOverHeap to tag random objects for ObjectFree evnts\n\n");
219 {
220 if (!NSK_JVMTI_VERIFY(jvmti->IterateOverHeap(JVMTI_HEAP_OBJECT_UNTAGGED,
221 heapObjectCallback,
222 &user_data))) {
223 nsk_jvmti_setFailStatus();
224 }
225 }
226 if (objectCount == 0) {
227 nsk_jvmti_setFailStatus();
228 NSK_COMPLAIN0("IterateOverHeap call had not visited any object\n\n");
229 } else {
230 NSK_DISPLAY1("Number of objects IterateOverHeap visited: %d\n\n", objectCount);
231 }
232
233 NSK_DISPLAY0("Let debugee to provoke GC\n");
234 if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
235 return;
236 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))
237 return;
238
239 NSK_DISPLAY0("Let debugee to finish\n");
240 if (!NSK_VERIFY(nsk_jvmti_resumeSync()))
241 return;
242 }
243
244 #ifdef STATIC_BUILD
Agent_OnLoad_ap10t001(JavaVM * jvm,char * options,void * reserved)245 JNIEXPORT jint JNICALL Agent_OnLoad_ap10t001(JavaVM *jvm, char *options, void *reserved) {
246 return Agent_Initialize(jvm, options, reserved);
247 }
Agent_OnAttach_ap10t001(JavaVM * jvm,char * options,void * reserved)248 JNIEXPORT jint JNICALL Agent_OnAttach_ap10t001(JavaVM *jvm, char *options, void *reserved) {
249 return Agent_Initialize(jvm, options, reserved);
250 }
JNI_OnLoad_ap10t001(JavaVM * jvm,char * options,void * reserved)251 JNIEXPORT jint JNI_OnLoad_ap10t001(JavaVM *jvm, char *options, void *reserved) {
252 return JNI_VERSION_1_8;
253 }
254 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)255 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
256 /* init framework and parse options */
257 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
258 return JNI_ERR;
259
260 /* create JVMTI environment */
261 if (!NSK_VERIFY((jvmti =
262 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
263 return JNI_ERR;
264
265 /* add capability to generate compiled method events */
266 memset(&caps, 0, sizeof(jvmtiCapabilities));
267 caps.can_tag_objects = 1;
268 caps.can_get_current_thread_cpu_time = 1;
269 caps.can_get_thread_cpu_time = 1;
270 caps.can_generate_object_free_events = 1;
271 caps.can_generate_garbage_collection_events = 1;
272 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
273 return JNI_ERR;
274
275 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
276 return JNI_ERR;
277
278 if (!caps.can_generate_garbage_collection_events)
279 NSK_DISPLAY0("Warning: generation of garbage collection events is not implemented\n");
280 if (!caps.can_generate_object_free_events)
281 NSK_DISPLAY0("Warning: generation of object free events is not implemented\n");
282 if (!caps.can_tag_objects)
283 NSK_DISPLAY0("Warning: tagging objects is not implemented\n");
284
285 /* set event callback */
286 NSK_DISPLAY0("setting event callbacks ...\n");
287 (void) memset(&callbacks, 0, sizeof(callbacks));
288
289 callbacks.GarbageCollectionStart = &GarbageCollectionStart;
290 callbacks.GarbageCollectionFinish = &GarbageCollectionFinish;
291 callbacks.ObjectFree = &ObjectFree;
292
293 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))))
294 return JNI_ERR;
295
296 NSK_DISPLAY0("setting event callbacks done\nenabling JVMTI events ...\n");
297 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE,
298 JVMTI_EVENT_GARBAGE_COLLECTION_START,
299 NULL)))
300 return JNI_ERR;
301 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE,
302 JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,
303 NULL)))
304 return JNI_ERR;
305 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE,
306 JVMTI_EVENT_OBJECT_FREE,
307 NULL)))
308 return JNI_ERR;
309 NSK_DISPLAY0("enabling the events done\n\n");
310
311 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
312 return JNI_ERR;
313
314 return JNI_OK;
315 }
316
317 }
318