8328741: serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java failed with unexpected owner
Reviewed-by: lmesnik, cjplummer
This commit is contained in:
parent
e681e9b4d7
commit
174d62652c
@ -53,9 +53,9 @@ public class ObjectMonitorUsage {
|
||||
static Object lockCheck = new Object();
|
||||
|
||||
native static int getRes();
|
||||
native static int waitsToEnter();
|
||||
native static int waitsToBeNotified();
|
||||
native static int setTestedMonitor(Object monitor);
|
||||
native static void ensureBlockedOnEnter(Thread thread);
|
||||
native static void ensureWaitingToBeNotified(Thread thread);
|
||||
native static void check(Object obj, Thread owner,
|
||||
int entryCount, int waiterCount, int notifyWaiterCount);
|
||||
|
||||
@ -87,10 +87,9 @@ public class ObjectMonitorUsage {
|
||||
Thread[] threads = new Thread[NUMBER_OF_WAITING_THREADS];
|
||||
for (int i = 0; i < NUMBER_OF_WAITING_THREADS; i++) {
|
||||
// the WaitingTask has to wait to be notified in lockCheck.wait()
|
||||
threads[i] = startTask(i, new WaitingTask(), isVirtual, "Waiting");
|
||||
}
|
||||
while (waitsToBeNotified() < NUMBER_OF_WAITING_THREADS) {
|
||||
sleep(1);
|
||||
Thread thread = startTask(i, new WaitingTask(), isVirtual, "Waiting");
|
||||
ensureWaitingToBeNotified(thread);
|
||||
threads[i] = thread;
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
@ -99,10 +98,9 @@ public class ObjectMonitorUsage {
|
||||
Thread[] threads = new Thread[NUMBER_OF_ENTERING_THREADS];
|
||||
for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
|
||||
// the EnteringTask has to be blocked at the lockCheck enter
|
||||
threads[i] = startTask(i, new EnteringTask(), isVirtual, "Entering");
|
||||
}
|
||||
while (waitsToEnter() < NUMBER_OF_ENTERING_THREADS) {
|
||||
sleep(1);
|
||||
Thread thread = startTask(i, new EnteringTask(), isVirtual, "Entering");
|
||||
ensureBlockedOnEnter(thread);
|
||||
threads[i] = thread;
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
|
@ -32,11 +32,8 @@ extern "C" {
|
||||
#define STATUS_FAILED 2
|
||||
|
||||
static jvmtiEnv *jvmti = nullptr;
|
||||
static jrawMonitorID event_lock = nullptr;
|
||||
static jint result = PASSED;
|
||||
static int check_idx = 0;
|
||||
static int waits_to_enter = 0;
|
||||
static int waits_to_be_notified = 0;
|
||||
static jobject tested_monitor = nullptr;
|
||||
|
||||
static bool is_tested_monitor(JNIEnv *jni, jobject monitor) {
|
||||
@ -53,47 +50,10 @@ static void log_event(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread,
|
||||
deallocate(jvmti, jni, (void*)tname);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
MonitorContendedEnter(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor) {
|
||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
||||
if (is_tested_monitor(jni, monitor)) {
|
||||
waits_to_enter++;
|
||||
log_event(jvmti, jni, thread, "MonitorContendedEnter", waits_to_enter);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
MonitorContendedEntered(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor) {
|
||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
||||
if (is_tested_monitor(jni, monitor)) {
|
||||
waits_to_enter--;
|
||||
log_event(jvmti, jni, thread, "MonitorContendedEntered", waits_to_enter);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
MonitorWait(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor, jlong timeout) {
|
||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
||||
if (is_tested_monitor(jni, monitor)) {
|
||||
waits_to_be_notified++;
|
||||
log_event(jvmti, jni, thread, "MonitorWait", waits_to_be_notified);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
MonitorWaited(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor, jboolean timed_out) {
|
||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
||||
if (is_tested_monitor(jni, monitor)) {
|
||||
waits_to_be_notified--;
|
||||
log_event(jvmti, jni, thread, "MonitorWaited", waits_to_be_notified);
|
||||
}
|
||||
}
|
||||
|
||||
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
|
||||
jint res;
|
||||
jvmtiError err;
|
||||
jvmtiCapabilities caps;
|
||||
jvmtiEventCallbacks callbacks;
|
||||
|
||||
res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
|
||||
if (res != JNI_OK || jvmti == nullptr) {
|
||||
@ -116,17 +76,6 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
|
||||
LOG("Warning: Monitor events are not implemented\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.MonitorContendedEnter = &MonitorContendedEnter;
|
||||
callbacks.MonitorContendedEntered = &MonitorContendedEntered;
|
||||
callbacks.MonitorWait = &MonitorWait;
|
||||
callbacks.MonitorWaited = &MonitorWaited;
|
||||
|
||||
err = jvmti->SetEventCallbacks(&callbacks, sizeof(jvmtiEventCallbacks));
|
||||
check_jvmti_error(err, "Agent_Initialize: error in JVMTI SetEventCallbacks");
|
||||
|
||||
event_lock = create_raw_monitor(jvmti, "Events Monitor");
|
||||
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
@ -216,41 +165,20 @@ Java_ObjectMonitorUsage_check(JNIEnv *jni, jclass cls, jobject obj, jthread owne
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_ObjectMonitorUsage_setTestedMonitor(JNIEnv *jni, jclass cls, jobject monitor) {
|
||||
jvmtiError err;
|
||||
jvmtiEventMode event_mode = (monitor != nullptr) ? JVMTI_ENABLE : JVMTI_DISABLE;
|
||||
|
||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
||||
|
||||
if (tested_monitor != nullptr) {
|
||||
jni->DeleteGlobalRef(tested_monitor);
|
||||
}
|
||||
tested_monitor = (monitor != nullptr) ? jni->NewGlobalRef(monitor) : nullptr;
|
||||
waits_to_enter = 0;
|
||||
waits_to_be_notified = 0;
|
||||
|
||||
err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_CONTENDED_ENTER, nullptr);
|
||||
check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #1");
|
||||
|
||||
err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, nullptr);
|
||||
check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #2");
|
||||
|
||||
err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_WAIT, nullptr);
|
||||
check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #3");
|
||||
|
||||
err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_WAITED, nullptr);
|
||||
check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #4");
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_ObjectMonitorUsage_waitsToEnter(JNIEnv *jni, jclass cls) {
|
||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
||||
return waits_to_enter;
|
||||
JNIEXPORT void JNICALL
|
||||
Java_ObjectMonitorUsage_ensureBlockedOnEnter(JNIEnv *jni, jclass cls, jthread thread) {
|
||||
wait_for_state(jvmti, jni, thread, JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_ObjectMonitorUsage_waitsToBeNotified(JNIEnv *jni, jclass cls) {
|
||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
||||
return waits_to_be_notified;
|
||||
JNIEXPORT void JNICALL
|
||||
Java_ObjectMonitorUsage_ensureWaitingToBeNotified(JNIEnv *jni, jclass cls, jthread thread) {
|
||||
wait_for_state(jvmti, jni, thread, JVMTI_THREAD_STATE_WAITING_INDEFINITELY);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
|
@ -216,11 +216,7 @@ test_vthread_resume_all(JNIEnv* jni, const jthread* thread_list, int suspend_mas
|
||||
check_jvmti_status(jni, err, "test_vthread_resume_all: error in JVMTI ResumeAllVirtualThreads");
|
||||
|
||||
// wait a second to give the breakpoints a chance to be hit.
|
||||
#ifdef WINDOWS
|
||||
Sleep(1000);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
sleep_sec(1);
|
||||
|
||||
for (int idx = 0; idx < EXCLUDE_CNT; idx++) {
|
||||
// Disable Breakpoint events on excluded thread
|
||||
|
@ -56,7 +56,7 @@
|
||||
|
||||
#define COMPLAIN LOG
|
||||
|
||||
|
||||
void sleep_ms(int millis);
|
||||
const char* TranslateState(jint flags);
|
||||
const char* TranslateError(jvmtiError err);
|
||||
|
||||
@ -380,6 +380,24 @@ find_method(jvmtiEnv *jvmti, JNIEnv *jni, jclass klass, const char* mname) {
|
||||
return method;
|
||||
}
|
||||
|
||||
// Wait for target thread to reach the required JVMTI thread state.
|
||||
// The state jint bitmask is returned by the JVMTI GetThreadState.
|
||||
// Some examples are:
|
||||
// - JVMTI_THREAD_STATE_WAITING
|
||||
// - JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
|
||||
// - JVMTI_THREAD_STATE_SLEEPING
|
||||
static void
|
||||
wait_for_state(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jint exp_state) {
|
||||
while (true) {
|
||||
// Allow a bitmask to designate expected thread state. E.g., if two bits are expected
|
||||
// than check they both are present in the state mask returned by JVMTI GetThreadState.
|
||||
if ((get_thread_state(jvmti, jni, thread) & exp_state) == exp_state) {
|
||||
break;
|
||||
}
|
||||
sleep_ms(100);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_FRAME_COUNT_PRINT_STACK_TRACE 200
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user