When JVM waits on a class loading lock, JVMTI_EVENT_MONITOR_WAITED is posted, but the corresponding JVMTI_EVENT_MONITOR_WAIT is not.
Though JVMTI Spec does not strictly prescribe when these events should occur (seeJDK-6455295), the common sense suggests that whenever an object waiting happens either both events should be posted or none at all.
Here is an example to demonstrate the issue:
(java -agentlib:monitorWaitAgent MonitorWait)
// MonitorWait.java
public class MonitorWait {
public static void main(String[] args) {
new Thread(Parent::new).start();
new Child();
}
static class Parent {
static {
try {
Thread.sleep(200);
} catch (Exception e) { /* ignore */ }
}
}
static class Child extends Parent {
}
}
// monitorWaitAgent.c
#include <jvmti.h>
#include <string.h>
#include <stdio.h>
void JNICALL MonitorWait(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, jobject object, jlong timeout) {
printf("> MonitorWait\n");
}
void JNICALL MonitorWaited(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, jobject object, jboolean timed_out) {
printf("< MonitorWaited\n");
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
jvmtiEnv* jvmti;
jvmtiEventCallbacks callbacks;
jvmtiCapabilities capabilities;
(*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_2);
memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_generate_monitor_events = 1;
(*jvmti)->AddCapabilities(jvmti, &capabilities);
memset(&callbacks, 0, sizeof(callbacks));
callbacks.MonitorWait = MonitorWait;
callbacks.MonitorWaited = MonitorWaited;
(*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAIT, NULL);
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAITED, NULL);
printf("Agent loaded\n");
return 0;
}
Though JVMTI Spec does not strictly prescribe when these events should occur (see
Here is an example to demonstrate the issue:
(java -agentlib:monitorWaitAgent MonitorWait)
// MonitorWait.java
public class MonitorWait {
public static void main(String[] args) {
new Thread(Parent::new).start();
new Child();
}
static class Parent {
static {
try {
Thread.sleep(200);
} catch (Exception e) { /* ignore */ }
}
}
static class Child extends Parent {
}
}
// monitorWaitAgent.c
#include <jvmti.h>
#include <string.h>
#include <stdio.h>
void JNICALL MonitorWait(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, jobject object, jlong timeout) {
printf("> MonitorWait\n");
}
void JNICALL MonitorWaited(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, jobject object, jboolean timed_out) {
printf("< MonitorWaited\n");
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
jvmtiEnv* jvmti;
jvmtiEventCallbacks callbacks;
jvmtiCapabilities capabilities;
(*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_2);
memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_generate_monitor_events = 1;
(*jvmti)->AddCapabilities(jvmti, &capabilities);
memset(&callbacks, 0, sizeof(callbacks));
callbacks.MonitorWait = MonitorWait;
callbacks.MonitorWaited = MonitorWaited;
(*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAIT, NULL);
(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAITED, NULL);
printf("Agent loaded\n");
return 0;
}
- relates to
-
JDK-6501158 Thread state is incorrect during class initialization procedure
-
- Closed
-
-
JDK-6455295 JVMTI Spec: Clarify the location at which MonitorWait/MonitorWaited events occur
-
- Closed
-
-
JDK-6380127 findMonitorDeadlockedThreads() hangs during Event-Main thread deadlock
-
- Closed
-