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 #include "JVMTITools.h"
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 /* ============================================================================= */
36
37 /* scaffold objects */
38 static JNIEnv* jni = NULL;
39 static jvmtiEnv *jvmti = NULL;
40 static jlong timeout = 0;
41 static jrawMonitorID syncLock = NULL;
42
43 /* constant names */
44 #define JVMTI_EVENT_COUNT (int)(JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL + 1)
45 #define EXPECTED_CLASS_NAME "Lnsk/jvmti/scenarios/events/EM01/em01t002a;"
46 #define CLASS_LOADER_COUNT_PARAM "classLoaderCount"
47
48 static int eventCount[JVMTI_EVENT_COUNT];
49
50 static int classLoaderCount = 0;
51
52 static jvmtiPhase currentPhase;
53
54 /* ============================================================================= */
55 /* ============================================================================= */
56
57
58 /*
59 * Class: nsk_jvmti_scenarios_events_EM01_em01t002
60 * Method: loadClass
61 * Signature: (Lnsk/share/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
62 */
63 JNIEXPORT jclass JNICALL
Java_nsk_jvmti_scenarios_events_EM01_em01t002_loadClass(JNIEnv * jni_env,jobject this,jobject loader,jstring className)64 Java_nsk_jvmti_scenarios_events_EM01_em01t002_loadClass(JNIEnv *jni_env,
65 jobject this, jobject loader, jstring className) {
66 jclass klass;
67 jmethodID methodID;
68 jclass loadedClass;
69
70 if (!NSK_JNI_VERIFY(jni_env, (klass =
71 NSK_CPP_STUB2(GetObjectClass, jni_env, loader)) != NULL)) {
72 nsk_jvmti_setFailStatus();
73 return NULL;
74 }
75
76 if (!NSK_JNI_VERIFY(jni_env, (methodID =
77 NSK_CPP_STUB4(GetMethodID, jni_env, klass, "loadClass",
78 "(Ljava/lang/String;)Ljava/lang/Class;")) != NULL)) {
79 nsk_jvmti_setFailStatus();
80 return NULL;
81 }
82
83 if (!NSK_JNI_VERIFY(jni_env, (loadedClass =
84 NSK_CPP_STUB4(CallObjectMethod, jni_env, loader, methodID,
85 className)) != NULL)) {
86 nsk_jvmti_setFailStatus();
87 return NULL;
88 }
89
90 return loadedClass;
91 }
92
93 /*
94 * Class: nsk_jvmti_scenarios_events_EM01_em01t002
95 * Method: prepareClass
96 * Signature: (Ljava/lang/Class;)Z
97 */
98 JNIEXPORT jboolean JNICALL
Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv * jni_env,jobject this,jclass klass)99 Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv *jni_env,
100 jobject this, jclass klass) {
101 jfieldID fieldID;
102
103 if (!NSK_JNI_VERIFY(jni_env, (fieldID =
104 NSK_CPP_STUB4(GetStaticFieldID, jni_env, klass,
105 "toProvokePreparation", "I")) != NULL)) {
106 nsk_jvmti_setFailStatus();
107 return NSK_FALSE;
108 }
109
110 return NSK_TRUE;
111 }
112
113 /*
114 * Class: nsk_jvmti_scenarios_events_EM01_em01t002
115 * Method: startThread
116 * Signature: (Ljava/lang/Thread;)Z
117 */
118 JNIEXPORT jboolean JNICALL
Java_nsk_jvmti_scenarios_events_EM01_em01t002_startThread(JNIEnv * jni_env,jobject this,jobject thread)119 Java_nsk_jvmti_scenarios_events_EM01_em01t002_startThread(JNIEnv *jni_env,
120 jobject this, jobject thread) {
121 jclass klass;
122 jmethodID methodID;
123
124 if (!NSK_JNI_VERIFY(jni_env, (klass =
125 NSK_CPP_STUB2(GetObjectClass, jni_env, thread)) != NULL)) {
126 nsk_jvmti_setFailStatus();
127 return NSK_FALSE;
128 }
129
130 if (!NSK_JNI_VERIFY(jni_env, (methodID =
131 NSK_CPP_STUB4(GetMethodID, jni_env, klass, "start", "()V")) != NULL)) {
132 nsk_jvmti_setFailStatus();
133 return NSK_FALSE;
134 }
135
136 if (!NSK_JNI_VERIFY_VOID(jni_env,
137 NSK_CPP_STUB3(CallVoidMethod, jni_env, thread, methodID)) ) {
138 nsk_jvmti_setFailStatus();
139 return NSK_FALSE;
140 }
141
142 return NSK_TRUE;
143 }
144
145 /* ============================================================================= */
146 /* ============================================================================= */
147
148 static void
changeCount(jvmtiEvent event)149 changeCount(jvmtiEvent event) {
150
151 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti, syncLock)))
152 nsk_jvmti_setFailStatus();
153
154 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL]++;
155
156 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti, syncLock)))
157 nsk_jvmti_setFailStatus();
158
159 }
160
161 /* ============================================================================= */
162
163 static void
showEventStatistics()164 showEventStatistics() {
165 int i;
166 const char* str;
167
168 NSK_DISPLAY0("Event statistics\n");
169 NSK_DISPLAY0("----------------\n");
170 for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
171 if (eventCount[i] > 0) {
172 str = TranslateEvent((jvmtiEvent)(i+JVMTI_MIN_EVENT_TYPE_VAL));
173 NSK_DISPLAY2("%-40s %7d\n", str, eventCount[i]);
174 }
175 }
176 }
177
178 /* ========================================================================== */
179
180 /* callbacks */
181 void
classEventsHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jclass klass)182 classEventsHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
183 jclass klass) {
184
185 char *className;
186 char *generic;
187 jvmtiPhase phase;
188
189 if (!NSK_JVMTI_VERIFY(
190 NSK_CPP_STUB4(GetClassSignature, jvmti_env, klass,
191 &className, &generic))) {
192 nsk_jvmti_setFailStatus();
193 return;
194 }
195
196 if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
197 changeCount(event);
198 NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
199 TranslateEvent(event),
200 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
201 className);
202 }
203
204 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) {
205 nsk_jvmti_setFailStatus();
206 }
207
208 if (phase != currentPhase) {
209 NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
210 TranslatePhase(phase), TranslatePhase(currentPhase));
211 }
212
213 if ((phase != JVMTI_PHASE_LIVE) && (phase != JVMTI_PHASE_START)) {
214 NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
215 TranslateEvent(event),
216 TranslatePhase(phase),
217 phase,
218 className);
219 nsk_jvmti_setFailStatus();
220 }
221
222 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
223 jvmti_env, (unsigned char*)className))) {
224 nsk_jvmti_setFailStatus();
225 }
226 if (generic != NULL)
227 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
228 jvmti_env, (unsigned char*)generic))) {
229 nsk_jvmti_setFailStatus();
230 }
231 }
232
233 void
threadEventHandler(jvmtiEvent event,jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)234 threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env,
235 jthread thread) {
236 jclass classObject;
237 char *className;
238 char *generic;
239 jvmtiPhase phase;
240
241
242 if (!NSK_JNI_VERIFY(jni_env, (classObject =
243 NSK_CPP_STUB2(GetObjectClass, jni_env, thread)) != NULL)) {
244 nsk_jvmti_setFailStatus();
245 return;
246 }
247
248 if (!NSK_JVMTI_VERIFY(
249 NSK_CPP_STUB4(GetClassSignature, jvmti_env, classObject,
250 &className, &generic))) {
251 nsk_jvmti_setFailStatus();
252 return;
253 }
254
255 if (strcmp(className, EXPECTED_CLASS_NAME) == 0) {
256 changeCount(event);
257 NSK_DISPLAY3("%25s(%4d)>>\tclass: %s\n",
258 TranslateEvent(event),
259 eventCount[event - JVMTI_MIN_EVENT_TYPE_VAL],
260 className);
261 }
262
263 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) {
264 nsk_jvmti_setFailStatus();
265 }
266
267 if (phase != currentPhase) {
268 NSK_DISPLAY2("Unexpected phase %s, but supposed %s",
269 TranslatePhase(phase), TranslatePhase(currentPhase));
270 }
271
272 if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
273 NSK_COMPLAIN4("%25s was sent during %s(%d)\n\tclass: %s\n",
274 TranslateEvent(event),
275 TranslatePhase(phase),
276 phase,
277 className);
278 nsk_jvmti_setFailStatus();
279 }
280
281 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
282 jvmti_env, (unsigned char*)className))) {
283 nsk_jvmti_setFailStatus();
284 }
285 if (generic != NULL)
286 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
287 jvmti_env, (unsigned char*)generic))) {
288 nsk_jvmti_setFailStatus();
289 }
290 }
291
292 JNIEXPORT void JNICALL
cbVMStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env)293 cbVMStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
294
295 jvmtiPhase phase;
296
297 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) {
298 nsk_jvmti_setFailStatus();
299 }
300
301 if ((phase != JVMTI_PHASE_START) && (phase != JVMTI_PHASE_LIVE)) {
302 NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
303 TranslateEvent(JVMTI_EVENT_VM_START),
304 TranslatePhase(phase),
305 phase);
306 nsk_jvmti_setFailStatus();
307 }
308
309 changeCount(JVMTI_EVENT_VM_START);
310 currentPhase = JVMTI_PHASE_START;
311 }
312
313 JNIEXPORT void JNICALL
cbVMInit(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)314 cbVMInit(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
315
316 jvmtiPhase phase;
317
318 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) {
319 nsk_jvmti_setFailStatus();
320 }
321
322 if (phase != JVMTI_PHASE_LIVE) {
323 NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
324 TranslateEvent(JVMTI_EVENT_VM_INIT),
325 TranslatePhase(phase),
326 phase);
327 nsk_jvmti_setFailStatus();
328 }
329
330 changeCount(JVMTI_EVENT_VM_INIT);
331 currentPhase = JVMTI_PHASE_LIVE;
332 }
333
334 JNIEXPORT void JNICALL
cbVMDeath(jvmtiEnv * jvmti_env,JNIEnv * jni_env)335 cbVMDeath(jvmtiEnv* jvmti_env, JNIEnv* jni_env) {
336
337 jvmtiPhase phase;
338
339 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) {
340 nsk_jvmti_setFailStatus();
341 }
342
343 if (phase != JVMTI_PHASE_LIVE) {
344 NSK_COMPLAIN3("%25s was sent during %s(%d)\n",
345 TranslateEvent(JVMTI_EVENT_VM_INIT),
346 TranslatePhase(phase),
347 phase);
348 nsk_jvmti_setFailStatus();
349 }
350
351 currentPhase = JVMTI_PHASE_DEAD;
352 changeCount(JVMTI_EVENT_VM_DEATH);
353
354 if (!NSK_JVMTI_VERIFY(
355 NSK_CPP_STUB2(DestroyRawMonitor, jvmti, syncLock)))
356 nsk_jvmti_setFailStatus();
357
358 }
359
360 JNIEXPORT void JNICALL
cbClassLoad(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)361 cbClassLoad(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
362 jclass klass) {
363
364 classEventsHandler(JVMTI_EVENT_CLASS_LOAD, jvmti_env, jni_env, klass);
365 }
366
367 JNIEXPORT void JNICALL
cbClassPrepare(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jclass klass)368 cbClassPrepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread,
369 jclass klass) {
370
371 classEventsHandler(JVMTI_EVENT_CLASS_PREPARE, jvmti_env, jni_env, klass);
372 }
373
374 JNIEXPORT void JNICALL
cbThreadStart(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)375 cbThreadStart(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
376
377 threadEventHandler(JVMTI_EVENT_THREAD_START, jvmti_env, jni_env, thread);
378 }
379
380 JNIEXPORT void JNICALL
cbThreadEnd(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread)381 cbThreadEnd(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) {
382
383 threadEventHandler(JVMTI_EVENT_THREAD_END, jvmti_env, jni_env, thread);
384 }
385
386 /* ============================================================================= */
387
388 static int
enableEvent(jvmtiEventMode enable,jvmtiEvent event)389 enableEvent(jvmtiEventMode enable, jvmtiEvent event) {
390
391 if (enable == JVMTI_ENABLE) {
392 NSK_DISPLAY1("enabling %s\n", TranslateEvent(event));
393 } else {
394 NSK_DISPLAY1("disabling %s\n", TranslateEvent(event));
395 }
396
397
398 if (!NSK_JVMTI_VERIFY(
399 NSK_CPP_STUB4(SetEventNotificationMode, jvmti, enable,
400 event, NULL))) {
401 nsk_jvmti_setFailStatus();
402 return NSK_FALSE;
403 }
404
405 return NSK_TRUE;
406 }
407
408 /* ============================================================================= */
409
410 /**
411 * Testcase: check tested events.
412 * - check if expected events received for each method
413 *
414 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break.
415 */
checkEvents(int step)416 int checkEvents(int step) {
417
418 int i;
419 jvmtiEvent curr;
420 int result = NSK_TRUE;
421 int mustBeChecked;
422
423 showEventStatistics();
424
425 for (i = 0; i < JVMTI_EVENT_COUNT; i++) {
426
427 curr = i + JVMTI_MIN_EVENT_TYPE_VAL;
428 switch (step) {
429 case 1:
430 mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
431 || (curr == JVMTI_EVENT_CLASS_PREPARE));
432 break;
433
434 case 2:
435 mustBeChecked = ((curr == JVMTI_EVENT_CLASS_LOAD)
436 || (curr == JVMTI_EVENT_CLASS_PREPARE)
437 || (curr == JVMTI_EVENT_THREAD_START)
438 || (curr == JVMTI_EVENT_THREAD_END));
439 break;
440 default:
441 mustBeChecked = NSK_TRUE;
442 }
443
444 if (mustBeChecked && eventCount[i] != classLoaderCount) {
445 nsk_jvmti_setFailStatus();
446 NSK_COMPLAIN3("Unexpected number of %s events %7d\n\texpected value %d\n",
447 TranslateEvent(curr),
448 eventCount[i],
449 classLoaderCount);
450 nsk_jvmti_setFailStatus();
451 result = NSK_FALSE;
452 }
453 }
454
455 return result;
456 }
457
458 /* ============================================================================= */
459
460 static int
setCallBacks()461 setCallBacks() {
462 jvmtiEventCallbacks eventCallbacks;
463 memset(&eventCallbacks, 0, sizeof(eventCallbacks));
464
465 eventCallbacks.VMStart = cbVMStart;
466 eventCallbacks.VMInit = cbVMInit;
467 eventCallbacks.VMDeath = cbVMDeath;
468 eventCallbacks.ClassLoad = cbClassLoad;
469 eventCallbacks.ClassPrepare = cbClassPrepare;
470 eventCallbacks.ThreadStart = cbThreadStart;
471 eventCallbacks.ThreadEnd = cbThreadEnd;
472
473 if (!NSK_JVMTI_VERIFY(
474 NSK_CPP_STUB3(SetEventCallbacks, jvmti,
475 &eventCallbacks,
476 sizeof(eventCallbacks))))
477 return NSK_FALSE;
478
479 return NSK_TRUE;
480 }
481
482 /* ============================================================================= */
483
484 /** Agent algorithm. */
485 static void JNICALL
agentProc(jvmtiEnv * jvmti,JNIEnv * agentJNI,void * arg)486 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
487
488 NSK_DISPLAY0("Wait for debuggee to become ready\n");
489 if (!nsk_jvmti_waitForSync(timeout))
490 return;
491
492 NSK_DISPLAY0("Let debuggee to load class\n");
493 if (!nsk_jvmti_resumeSync())
494 return;
495
496 if (!nsk_jvmti_waitForSync(timeout))
497 return;
498
499 /* check only CLASS_LOAD and CLASS_PREPARE events */
500 if (!checkEvents(1)) {
501 nsk_jvmti_setFailStatus();
502 }
503
504 NSK_DISPLAY0("Let debuggee to start threads\n");
505 if (!nsk_jvmti_resumeSync())
506 return;
507
508 if (!nsk_jvmti_waitForSync(timeout))
509 return;
510
511 NSK_DISPLAY0("check event 2\n");
512 if (!checkEvents(2)) {
513 nsk_jvmti_setFailStatus();
514 }
515
516 NSK_DISPLAY0("Let debuggee to finish\n");
517 if (!nsk_jvmti_resumeSync())
518 return;
519
520 }
521
522 /* ============================================================================= */
523
524 /** Agent library initialization. */
525 #ifdef STATIC_BUILD
Agent_OnLoad_em01t002(JavaVM * jvm,char * options,void * reserved)526 JNIEXPORT jint JNICALL Agent_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) {
527 return Agent_Initialize(jvm, options, reserved);
528 }
Agent_OnAttach_em01t002(JavaVM * jvm,char * options,void * reserved)529 JNIEXPORT jint JNICALL Agent_OnAttach_em01t002(JavaVM *jvm, char *options, void *reserved) {
530 return Agent_Initialize(jvm, options, reserved);
531 }
JNI_OnLoad_em01t002(JavaVM * jvm,char * options,void * reserved)532 JNIEXPORT jint JNI_OnLoad_em01t002(JavaVM *jvm, char *options, void *reserved) {
533 return JNI_VERSION_1_8;
534 }
535 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)536 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
537
538 currentPhase = JVMTI_PHASE_ONLOAD;
539
540 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
541 return JNI_ERR;
542
543 timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
544 classLoaderCount = nsk_jvmti_findOptionIntValue(CLASS_LOADER_COUNT_PARAM, 10);
545
546 if (!NSK_VERIFY((jvmti = nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
547 return JNI_ERR;
548
549 if (!NSK_JVMTI_VERIFY(
550 NSK_CPP_STUB3(CreateRawMonitor, jvmti, "_syncLock", &syncLock))) {
551 nsk_jvmti_setFailStatus();
552 return JNI_ERR;
553 }
554
555 if (!setCallBacks()) {
556 return JNI_ERR;
557 }
558
559 if (!enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD)
560 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE)
561 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START)
562 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END)
563 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_START)
564 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT)
565 || !enableEvent(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH)
566 ) {
567 NSK_COMPLAIN0("Events could not be enabled");
568 nsk_jvmti_setFailStatus();
569 return JNI_ERR;
570 }
571
572 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
573 return JNI_ERR;
574
575 currentPhase = JVMTI_PHASE_PRIMORDIAL;
576
577 return JNI_OK;
578 }
579
580 #ifdef __cplusplus
581 }
582 #endif
583