11/*
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.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,8 @@ extern "C" {
4747#define FAILED 2
4848
4949static jint result = PASSED ;
50+ static jrawMonitorID event_mon = NULL ;
51+ static jboolean is_vm_dead = JNI_FALSE ;
5052
5153static jint Agent_Initialize (JavaVM * jvm , char * options , void * reserved );
5254
@@ -68,7 +70,7 @@ jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
6870static void check_jvmti_error (jvmtiEnv * jvmti , char * fname , jvmtiError err ) {
6971 if (err != JVMTI_ERROR_NONE ) {
7072 printf (" ## %s error: %d\n" , fname , err );
71- exit ( err );
73+ abort ( );
7274 }
7375}
7476
@@ -317,7 +319,7 @@ VMStart(jvmtiEnv *jvmti, JNIEnv* jni) {
317319}
318320
319321static void JNICALL
320- VMInit (jvmtiEnv * jvmti , JNIEnv * jnii , jthread thread ) {
322+ VMInit (jvmtiEnv * jvmti , JNIEnv * jni , jthread thread ) {
321323 jvmtiPhase phase ;
322324
323325 printf ("VMInit event\n" );
@@ -329,22 +331,52 @@ VMInit(jvmtiEnv *jvmti, JNIEnv* jnii, jthread thread) {
329331 }
330332}
331333
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+
332349static void JNICALL
333350ClassPrepare (jvmtiEnv * jvmti , JNIEnv * env , jthread thread , jclass klass ) {
334351 static const jint EVENTS_LIMIT = 2 ;
335352 static jint event_no = 0 ;
336- jthread cur_thread = get_cur_thread (jvmti );
337353 jvmtiPhase phase ;
338354 intptr_t exp_val = 777 ;
339355 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 );
340362
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+ }
341369 get_phase (jvmti , & phase );
342370 if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE ) {
343371 printf (" ## Error: unexpected phase: %d, expected: %d or %d\n" ,
344372 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 );
345376 return ;
346377 }
347378 if (phase == JVMTI_PHASE_START && event_no < EVENTS_LIMIT ) {
379+ jthread cur_thread = get_cur_thread (jvmti );
348380 printf ("\nClassPrepare event during the start phase: #%d\n" , event_no );
349381 // Test the JVMTI class functions during the start phase
350382 test_class_functions (jvmti , env , thread , klass );
@@ -360,6 +392,8 @@ ClassPrepare(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) {
360392 }
361393 event_no ++ ;
362394 }
395+ err = (* jvmti )-> RawMonitorExit (jvmti , event_mon );
396+ check_jvmti_error (jvmti , "ClassPrepare event: Failed in RawMonitorExit" , err );
363397}
364398
365399static
@@ -400,6 +434,9 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
400434 callbacks .VMInit = VMInit ;
401435 callbacks .ClassPrepare = ClassPrepare ;
402436
437+ err = (* jvmti )-> CreateRawMonitor (jvmti , "Events Monitor" , & event_mon );
438+ check_jvmti_error (jvmti , "## Agent_Initialize: CreateRawMonitor" , err );
439+
403440 err = (* jvmti )-> SetEventCallbacks (jvmti , & callbacks , size );
404441 check_jvmti_error (jvmti , "## Agent_Initialize: SetEventCallbacks" , err );
405442
0 commit comments