11/*
2- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
33 * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
44 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55 *
@@ -47,12 +47,36 @@ extern "C" {
4747
4848#endif
4949
50+ // JVMTI_ERROR_WRONG_PHASE guard
51+ static jrawMonitorID event_mon = NULL ;
52+ static int is_vm_dead = 0 ;
53+
54+ void lock (jvmtiEnv * jvmti , JNIEnv * jni ) {
55+ jvmtiError err = (* jvmti )-> RawMonitorEnter (jvmti , event_mon );
56+ if (err != JVMTI_ERROR_NONE ) {
57+ JNI_ENV_PTR (jni )-> FatalError (JNI_ENV_ARGS2 (jni , "RawMonitorEnter failed" ));
58+ }
59+ }
60+
61+ void unlock (jvmtiEnv * jvmti , JNIEnv * jni ) {
62+ jvmtiError err = (* jvmti )-> RawMonitorExit (jvmti , event_mon );
63+ if (err != JVMTI_ERROR_NONE ) {
64+ JNI_ENV_PTR (jni )-> FatalError (JNI_ENV_ARGS2 (jni , "RawMonitorExit failed" ));
65+ }
66+ }
67+
5068extern JNIEXPORT void JNICALL VMObjectAlloc (jvmtiEnv * jvmti ,
5169 JNIEnv * jni ,
5270 jthread thread ,
5371 jobject object ,
5472 jclass klass ,
5573 jlong size ) {
74+ lock (jvmti , jni );
75+ if (is_vm_dead ) {
76+ unlock (jvmti , jni );
77+ return ;
78+ }
79+
5680 char * signature = NULL ;
5781 jvmtiError error = (* jvmti )-> GetClassSignature (jvmti , klass , & signature , NULL );
5882
@@ -78,32 +102,48 @@ extern JNIEXPORT void JNICALL VMObjectAlloc(jvmtiEnv *jvmti,
78102 JNI_ENV_ARGS2 (jni , "Failed during the CallObjectMethod call" ));
79103 }
80104 }
105+ unlock (jvmti , jni );
81106}
82107
83108extern JNIEXPORT void JNICALL OnVMInit (jvmtiEnv * jvmti , JNIEnv * jni , jthread thread ) {
84109 (* jvmti )-> SetEventNotificationMode (jvmti , JVMTI_ENABLE , JVMTI_EVENT_VM_OBJECT_ALLOC , NULL );
85110}
86111
112+ extern JNIEXPORT void JNICALL OnVMDeath (jvmtiEnv * jvmti , JNIEnv * jni ) {
113+ lock (jvmti , jni );
114+ is_vm_dead = 1 ;
115+ unlock (jvmti , jni );
116+ }
117+
87118extern JNIEXPORT jint JNICALL Agent_OnLoad (JavaVM * jvm , char * options ,
88119 void * reserved ) {
89120 jvmtiEnv * jvmti ;
90121 jvmtiEventCallbacks callbacks ;
91122 jvmtiCapabilities caps ;
123+ jvmtiError err ;
92124
93125 if ((* jvm )-> GetEnv (jvm , (void * * ) (& jvmti ), JVMTI_VERSION ) != JNI_OK ) {
94126 return JNI_ERR ;
95127 }
96128
129+ err = (* jvmti )-> CreateRawMonitor (jvmti , "Event Monitor" , & event_mon );
130+ if (err != JVMTI_ERROR_NONE ) {
131+ printf ("CreateRawMonitor failed: %d\n" , err );
132+ return JNI_ERR ;
133+ }
134+
97135 memset (& callbacks , 0 , sizeof (callbacks ));
98136 callbacks .VMObjectAlloc = & VMObjectAlloc ;
99137 callbacks .VMInit = & OnVMInit ;
138+ callbacks .VMDeath = & OnVMDeath ;
100139
101140 memset (& caps , 0 , sizeof (caps ));
102141 caps .can_generate_vm_object_alloc_events = 1 ;
103142 (* jvmti )-> AddCapabilities (jvmti , & caps );
104143
105144 (* jvmti )-> SetEventCallbacks (jvmti , & callbacks , sizeof (jvmtiEventCallbacks ));
106145 (* jvmti )-> SetEventNotificationMode (jvmti , JVMTI_ENABLE , JVMTI_EVENT_VM_INIT , NULL );
146+ (* jvmti )-> SetEventNotificationMode (jvmti , JVMTI_ENABLE , JVMTI_EVENT_VM_DEATH , NULL );
107147 return 0 ;
108148}
109149
0 commit comments