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