1 /*
2 * Copyright (c) 2004, 2019, 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 "ExceptionCheckingJniEnv.hpp"
28 #include "jni_tools.h"
29 #include "jvmti_tools.h"
30 #include "JVMTITools.h"
31
32 extern "C" {
33
34 /* ============================================================================= */
35
36 /* scaffold objects */
37 static JNIEnv* jni = NULL;
38 static jvmtiEnv *jvmti = NULL;
39 static jlong timeout = 0;
40 static jrawMonitorID syncLock = NULL;
41
42 /* constant names */
43 #define JVMTI_EVENT_COUNT (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1)
44 #define EXPECTED_CLASS_NAME "Lnsk/jvmti/scenarios/events/EM01/em01t001a;"
45 #define CLASS_LOADER_COUNT_PARAM "classLoaderCount"
46
47 static int eventCount[JVMTI_EVENT_COUNT];
48
49 static int classLoaderCount = 0;
50
51 static jvmtiPhase currentPhase;
52
53 /* ============================================================================= */
54
55 static void
changeCount(jvmtiEvent event)56 changeCount(jvmtiEvent event) {
57
58 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(syncLock)))
59 nsk_jvmti_setFailStatus();
60
61 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
62
63 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(syncLock)))
64 nsk_jvmti_setFailStatus();
65
66 }
67
68 /* ============================================================================= */
69
70 static void
showEventStatistics()71 showEventStatistics() {
72 int i;
73 const char* str;
74
75 NSK_DISPLAY0("Event statistics\n");
76 NSK_DISPLAY0("----------------\n");
77 for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
78 if (eventCount[i] > 0) {
79 str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
80 NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]);
81 }
82 }
83 }
84
85 /* ========================================================================== */
86
87 /* callbacks */
88 void
classEventsHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jclass klass)89 classEventsHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
90 jclass klass) {
91
92 char *className;
93 char *generic;
94 jvmtiPhase phase;
95
96 if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, &generic))) {
97 nsk_jvmti_setFailStatus();
98 return;
99 }
100
101 if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
102 changeCount(event);
103 NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
104 TranslateEvent(event),
105 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
106 className);
107 }
108
109 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
110 nsk_jvmti_setFailStatus();
111 }
112
113 if (phase != currentPhase) {
114 NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
115 TranslatePhase(phase), TranslatePhase(currentPhase));
116 }
117
118 if ((phase != JVMTI_PHASE_LIVE) && (phase != JVMTI_PHASE_START)) {
119 NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
120 TranslateEvent(event),
121 TranslatePhase(phase),
122 phase,
123 className);
124 nsk_jvmti_setFailStatus();
125 }
126
127 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
128 nsk_jvmti_setFailStatus();
129 }
130 if (generic != NULL)
131 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
132 nsk_jvmti_setFailStatus();
133 }
134 }
135
136 void
threadEventHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)137 threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
138 jthread thread) {
139 ExceptionCheckingJniEnvPtr ec_jni(jni_env);
140 jclass classObject;
141 char *className;
142 char *generic;
143 jvmtiPhase phase;
144
145 classObject = ec_jni->GetObjectClass(thread, TRACE_JNI_CALL);
146
147 if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classObject, &className, &generic))) {
148 nsk_jvmti_setFailStatus();
149 return;
150 }
151
152 if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
153 changeCount(event);
154 NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
155 TranslateEvent(event),
156 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
157 className);
158 }
159
160 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
161 nsk_jvmti_setFailStatus();
162 }
163
164 if (phase != currentPhase) {
165 NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
166 TranslatePhase(phase), TranslatePhase(currentPhase));
167 }
168
169 if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
170 NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
171 TranslateEvent(event),
172 TranslatePhase(phase),
173 phase,
174 className);
175 nsk_jvmti_setFailStatus();
176 }
177
178 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) {
179 nsk_jvmti_setFailStatus();
180 }
181 if (generic != NULL)
182 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) {
183 nsk_jvmti_setFailStatus();
184 }
185 }
186
187 JNIEXPORT void JNICALL
cbVMStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env)188 cbVMStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
189
190 jvmtiPhase phase;
191
192 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
193 nsk_jvmti_setFailStatus();
194 }
195
196 if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
197 NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
198 TranslateEvent(JVMTI_EVENT_VM_START),
199 TranslatePhase(phase),
200 phase);
201 nsk_jvmti_setFailStatus();
202 }
203
204 changeCount(JVMTI_EVENT_VM_START);
205 currentPhase = JVMTI_PHASE_START;
206 }
207
208 JNIEXPORT void JNICALL
cbVMInit(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)209 cbVMInit(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
210
211 jvmtiPhase phase;
212
213 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
214 nsk_jvmti_setFailStatus();
215 }
216
217 if (phase != JVMTI_PHASE_LIVE) {
218 NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
219 TranslateEvent(JVMTI_EVENT_VM_INIT),
220 TranslatePhase(phase),
221 phase);
222 nsk_jvmti_setFailStatus();
223 }
224
225 changeCount(JVMTI_EVENT_VM_INIT);
226 currentPhase = JVMTI_PHASE_LIVE;
227 }
228
229 JNIEXPORT void JNICALL
cbVMDeath(jvmtiEnv * jvmti_env,JNIEnv * jni_env)230 cbVMDeath(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
231
232 jvmtiPhase phase;
233
234 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
235 nsk_jvmti_setFailStatus();
236 }
237
238 if (phase != JVMTI_PHASE_LIVE) {
239 NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
240 TranslateEvent(JVMTI_EVENT_VM_INIT),
241 TranslatePhase(phase),
242 phase);
243 nsk_jvmti_setFailStatus();
244 }
245
246 currentPhase = JVMTI_PHASE_DEAD;
247 changeCount(JVMTI_EVENT_VM_DEATH);
248
249 if (!NSK_JVMTI_VERIFY(jvmti->DestroyRawMonitor(syncLock)))
250 nsk_jvmti_setFailStatus();
251
252 }
253
254 JNIEXPORT void JNICALL
cbClassLoad(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)255 cbClassLoad(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
256 jclass klass) {
257
258 classEventsHandler(JVMTI_EVENT_CLASS_LOAD, jvmti_env, jni_env, klass);
259 }
260
261 JNIEXPORT void JNICALL
cbClassPrepare(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)262 cbClassPrepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
263 jclass klass) {
264
265 classEventsHandler(JVMTI_EVENT_CLASS_PREPARE, jvmti_env, jni_env, klass);
266 }
267
268 JNIEXPORT void JNICALL
cbThreadStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)269 cbThreadStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
270
271 threadEventHandler(JVMTI_EVENT_THREAD_START, jvmti_env, jni_env, thread);
272 }
273
274 JNIEXPORT void JNICALL
cbThreadEnd(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)275 cbThreadEnd(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
276
277 threadEventHandler(JVMTI_EVENT_THREAD_END, jvmti_env, jni_env, thread);
278 }
279
280 /* ============================================================================= */
281
282 static int
enableEvent(jvmtiEventMode enable,jvmtiEvent event)283 enableEvent(jvmtiEventMode enable, jvmtiEvent event) {
284 NSK_DISPLAY1("enabling %s\n", TranslateEvent(event));
285 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(enable, event, NULL))) {
286 nsk_jvmti_setFailStatus();
287 return NSK_FALSE;
288 }
289
290 return NSK_TRUE;
291 }
292
293 /* ============================================================================= */
294
295 /**
296 * Testcase: check tested events.
297 * - check if expected events received for each method
298 *
299 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break.
300 */
checkEvents(int step)301 int checkEvents(int step) {
302
303 int i;
304 jvmtiEvent curr;
305 int result = NSK_TRUE;
306 int mustBeChecked;
307
308 showEventStatistics();
309
310 for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
311
312 curr = (jvmtiEvent) (i + JVMTI_MIN_EVENT_TYPE_VAL);
313 switch (step) {
314 case 1:
315 mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
316 || (curr == JVMTI_EVENT_CLASS_PREPARE));
317 break;
318
319 case 2:
320 mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
321 || (curr == JVMTI_EVENT_CLASS_PREPARE)
322 || (curr == JVMTI_EVENT_THREAD_START)
323 || (curr == JVMTI_EVENT_THREAD_END));
324 break;
325 default:
326 mustBeChecked = NSK_TRUE;
327 }
328
329 if (mustBeChecked && eventCount[i] != classLoaderCount) {
330 nsk_jvmti_setFailStatus();
331 NSK_COMPLAIN3("Unexpected number of %s events %7d\n\texpected value %d\n",
332 TranslateEvent(curr),
333 eventCount[i],
334 classLoaderCount);
335 nsk_jvmti_setFailStatus();
336 result = NSK_FALSE;
337 }
338 }
339
340 return result;
341 }
342
343 /* ============================================================================= */
344
345 static int
setCallBacks()346 setCallBacks() {
347 jvmtiEventCallbacks eventCallbacks;
348 memset(&eventCallbacks, 0, sizeof(eventCallbacks));
349
350 eventCallbacks.VMStart = cbVMStart;
351 eventCallbacks.VMInit = cbVMInit;
352 eventCallbacks.VMDeath = cbVMDeath;
353 eventCallbacks.ClassLoad = cbClassLoad;
354 eventCallbacks.ClassPrepare = cbClassPrepare;
355 eventCallbacks.ThreadStart = cbThreadStart;
356 eventCallbacks.ThreadEnd = cbThreadEnd;
357
358 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks))))
359 return NSK_FALSE;
360
361 return NSK_TRUE;
362 }
363
364 /* ============================================================================= */
365
366 /** Agent algorithm. */
367 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * agentJNI,void * arg)368 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
369
370 NSK_DISPLAY0("Wait for debuggee to become ready\n");
371 if (!nsk_jvmti_waitForSync(timeout))
372 return;
373
374 NSK_DISPLAY0("Let debuggee to load class\n");
375 if (!nsk_jvmti_resumeSync())
376 return;
377
378 if (!nsk_jvmti_waitForSync(timeout))
379 return;
380
381 /* check only CLASS_LOAD and CLASS_PREPARE events */
382 if (!checkEvents(1)) {
383 nsk_jvmti_setFailStatus();
384 }
385
386 NSK_DISPLAY0("Let debuggee to start threads\n");
387 if (!nsk_jvmti_resumeSync())
388 return;
389
390 if (!nsk_jvmti_waitForSync(timeout))
391 return;
392
393 NSK_DISPLAY0("check event 2\n");
394 if (!checkEvents(2)) {
395 nsk_jvmti_setFailStatus();
396 NSK_DISPLAY0("fail\n");
397 }
398
399 NSK_DISPLAY0("Let debuggee to finish\n");
400 if (!nsk_jvmti_resumeSync())
401 return;
402
403 }
404
405 /* ============================================================================= */
406
407 /** Agent library initialization. */
408 #ifdef STATIC_BUILD
Agent_OnLoad_em01t001(JavaVM * jvm,char * options,void * reserved)409 JNIEXPORT jint JNICALL Agent_OnLoad_em01t001(JavaVM *jvm, char *options, void *reserved) {
410 return Agent_Initialize(jvm, options, reserved);
411 }
Agent_OnAttach_em01t001(JavaVM * jvm,char * options,void * reserved)412 JNIEXPORT jint JNICALL Agent_OnAttach_em01t001(JavaVM *jvm, char *options, void *reserved) {
413 return Agent_Initialize(jvm, options, reserved);
414 }
JNI_OnLoad_em01t001(JavaVM * jvm,char * options,void * reserved)415 JNIEXPORT jint JNI_OnLoad_em01t001(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
421 currentPhase = JVMTI_PHASE_ONLOAD;
422
423 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
424 return JNI_ERR;
425
426 timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
427 classLoaderCount = nsk_jvmti_findOptionIntValue(CLASS_LOADER_COUNT_PARAM, 10);
428
429 jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved);
430 if (!NSK_VERIFY(jvmti != NULL))
431 return JNI_ERR;
432
433 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_syncLock", &syncLock))) {
434 nsk_jvmti_setFailStatus();
435 return JNI_ERR;
436 }
437
438 if (!setCallBacks()) {
439 return JNI_ERR;
440 }
441
442 if (!enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD)
443 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE)
444 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START)
445 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END)
446 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_START)
447 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT)
448 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH)
449 ) {
450 NSK_COMPLAIN0("Events could not be enabled");
451 nsk_jvmti_setFailStatus();
452 return JNI_ERR;
453 }
454
455 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
456 return JNI_ERR;
457
458 currentPhase = JVMTI_PHASE_PRIMORDIAL;
459
460 return JNI_OK;
461 }
462
463 }
464