1
1
/*
2
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,8 @@ extern "C" {
47
47
#define FAILED 2
48
48
49
49
static jint result = PASSED ;
50
+ static jrawMonitorID event_mon = NULL ;
51
+ static jboolean is_vm_dead = JNI_FALSE ;
50
52
51
53
static jint Agent_Initialize (JavaVM * jvm , char * options , void * reserved );
52
54
@@ -68,7 +70,7 @@ jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
68
70
static void check_jvmti_error (jvmtiEnv * jvmti , char * fname , jvmtiError err ) {
69
71
if (err != JVMTI_ERROR_NONE ) {
70
72
printf (" ## %s error: %d\n" , fname , err );
71
- exit ( err );
73
+ abort ( );
72
74
}
73
75
}
74
76
@@ -317,7 +319,7 @@ VMStart(jvmtiEnv *jvmti, JNIEnv* jni) {
317
319
}
318
320
319
321
static void JNICALL
320
- VMInit (jvmtiEnv * jvmti , JNIEnv * jnii , jthread thread ) {
322
+ VMInit (jvmtiEnv * jvmti , JNIEnv * jni , jthread thread ) {
321
323
jvmtiPhase phase ;
322
324
323
325
printf ("VMInit event\n" );
@@ -329,22 +331,52 @@ VMInit(jvmtiEnv *jvmti, JNIEnv* jnii, jthread thread) {
329
331
}
330
332
}
331
333
334
+ static void JNICALL
335
+ VMDeath (jvmtiEnv * jvmti , JNIEnv * jni ) {
336
+ jvmtiError err ;
337
+
338
+ // Block ClassPrepare events while this callback is executed.
339
+ err = (* jvmti )-> RawMonitorEnter (jvmti , event_mon );
340
+ check_jvmti_error (jvmti , "VMDeath event: Failed in RawMonitorEnter" , err );
341
+
342
+ is_vm_dead = JNI_TRUE ;
343
+ printf ("VMDeath event\n" );
344
+
345
+ err = (* jvmti )-> RawMonitorExit (jvmti , event_mon );
346
+ check_jvmti_error (jvmti , "VMDeath event: Failed in RawMonitorExit" , err );
347
+ }
348
+
332
349
static void JNICALL
333
350
ClassPrepare (jvmtiEnv * jvmti , JNIEnv * env , jthread thread , jclass klass ) {
334
351
static const jint EVENTS_LIMIT = 2 ;
335
352
static jint event_no = 0 ;
336
- jthread cur_thread = get_cur_thread (jvmti );
337
353
jvmtiPhase phase ;
338
354
intptr_t exp_val = 777 ;
339
355
intptr_t act_val ;
356
+ jvmtiError err ;
357
+
358
+ // Block VMDeath event and other ClassPrepare events while this callback is executed.
359
+ // Sync with VMDeath event and check for is_vm_dead guard against JVMTI_ERROR WRONG_PHASE.
360
+ err = (* jvmti )-> RawMonitorEnter (jvmti , event_mon );
361
+ check_jvmti_error (jvmti , "ClassPrepare event: Failed in RawMonitorEnter" , err );
340
362
363
+ if (is_vm_dead ) {
364
+ printf ("\nIgnoring ClassPrepare event during the dead phase\n" );
365
+ err = (* jvmti )-> RawMonitorExit (jvmti , event_mon );
366
+ check_jvmti_error (jvmti , "ClassPrepare event: Failed in RawMonitorExit" , err );
367
+ return ;
368
+ }
341
369
get_phase (jvmti , & phase );
342
370
if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE ) {
343
371
printf (" ## Error: unexpected phase: %d, expected: %d or %d\n" ,
344
372
phase , JVMTI_PHASE_START , JVMTI_PHASE_LIVE );
373
+ result = FAILED ;
374
+ err = (* jvmti )-> RawMonitorExit (jvmti , event_mon );
375
+ check_jvmti_error (jvmti , "ClassPrepare event: Failed in RawMonitorExit" , err );
345
376
return ;
346
377
}
347
378
if (phase == JVMTI_PHASE_START && event_no < EVENTS_LIMIT ) {
379
+ jthread cur_thread = get_cur_thread (jvmti );
348
380
printf ("\nClassPrepare event during the start phase: #%d\n" , event_no );
349
381
// Test the JVMTI class functions during the start phase
350
382
test_class_functions (jvmti , env , thread , klass );
@@ -360,6 +392,8 @@ ClassPrepare(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) {
360
392
}
361
393
event_no ++ ;
362
394
}
395
+ err = (* jvmti )-> RawMonitorExit (jvmti , event_mon );
396
+ check_jvmti_error (jvmti , "ClassPrepare event: Failed in RawMonitorExit" , err );
363
397
}
364
398
365
399
static
@@ -400,6 +434,9 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
400
434
callbacks .VMInit = VMInit ;
401
435
callbacks .ClassPrepare = ClassPrepare ;
402
436
437
+ err = (* jvmti )-> CreateRawMonitor (jvmti , "Events Monitor" , & event_mon );
438
+ check_jvmti_error (jvmti , "## Agent_Initialize: CreateRawMonitor" , err );
439
+
403
440
err = (* jvmti )-> SetEventCallbacks (jvmti , & callbacks , size );
404
441
check_jvmti_error (jvmti , "## Agent_Initialize: SetEventCallbacks" , err );
405
442
0 commit comments