8328741: serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java failed with unexpected owner
Reviewed-by: lmesnik, cjplummer
This commit is contained in:
parent
e681e9b4d7
commit
174d62652c
test
hotspot/jtreg/serviceability/jvmti
ObjectMonitorUsage
vthread/SuspendResumeAll
lib/jdk/test/lib/jvmti
@ -53,9 +53,9 @@ public class ObjectMonitorUsage {
|
|||||||
static Object lockCheck = new Object();
|
static Object lockCheck = new Object();
|
||||||
|
|
||||||
native static int getRes();
|
native static int getRes();
|
||||||
native static int waitsToEnter();
|
|
||||||
native static int waitsToBeNotified();
|
|
||||||
native static int setTestedMonitor(Object monitor);
|
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,
|
native static void check(Object obj, Thread owner,
|
||||||
int entryCount, int waiterCount, int notifyWaiterCount);
|
int entryCount, int waiterCount, int notifyWaiterCount);
|
||||||
|
|
||||||
@ -87,10 +87,9 @@ public class ObjectMonitorUsage {
|
|||||||
Thread[] threads = new Thread[NUMBER_OF_WAITING_THREADS];
|
Thread[] threads = new Thread[NUMBER_OF_WAITING_THREADS];
|
||||||
for (int i = 0; i < NUMBER_OF_WAITING_THREADS; i++) {
|
for (int i = 0; i < NUMBER_OF_WAITING_THREADS; i++) {
|
||||||
// the WaitingTask has to wait to be notified in lockCheck.wait()
|
// the WaitingTask has to wait to be notified in lockCheck.wait()
|
||||||
threads[i] = startTask(i, new WaitingTask(), isVirtual, "Waiting");
|
Thread thread = startTask(i, new WaitingTask(), isVirtual, "Waiting");
|
||||||
}
|
ensureWaitingToBeNotified(thread);
|
||||||
while (waitsToBeNotified() < NUMBER_OF_WAITING_THREADS) {
|
threads[i] = thread;
|
||||||
sleep(1);
|
|
||||||
}
|
}
|
||||||
return threads;
|
return threads;
|
||||||
}
|
}
|
||||||
@ -99,10 +98,9 @@ public class ObjectMonitorUsage {
|
|||||||
Thread[] threads = new Thread[NUMBER_OF_ENTERING_THREADS];
|
Thread[] threads = new Thread[NUMBER_OF_ENTERING_THREADS];
|
||||||
for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
|
for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
|
||||||
// the EnteringTask has to be blocked at the lockCheck enter
|
// the EnteringTask has to be blocked at the lockCheck enter
|
||||||
threads[i] = startTask(i, new EnteringTask(), isVirtual, "Entering");
|
Thread thread = startTask(i, new EnteringTask(), isVirtual, "Entering");
|
||||||
}
|
ensureBlockedOnEnter(thread);
|
||||||
while (waitsToEnter() < NUMBER_OF_ENTERING_THREADS) {
|
threads[i] = thread;
|
||||||
sleep(1);
|
|
||||||
}
|
}
|
||||||
return threads;
|
return threads;
|
||||||
}
|
}
|
||||||
|
@ -32,11 +32,8 @@ extern "C" {
|
|||||||
#define STATUS_FAILED 2
|
#define STATUS_FAILED 2
|
||||||
|
|
||||||
static jvmtiEnv *jvmti = nullptr;
|
static jvmtiEnv *jvmti = nullptr;
|
||||||
static jrawMonitorID event_lock = nullptr;
|
|
||||||
static jint result = PASSED;
|
static jint result = PASSED;
|
||||||
static int check_idx = 0;
|
static int check_idx = 0;
|
||||||
static int waits_to_enter = 0;
|
|
||||||
static int waits_to_be_notified = 0;
|
|
||||||
static jobject tested_monitor = nullptr;
|
static jobject tested_monitor = nullptr;
|
||||||
|
|
||||||
static bool is_tested_monitor(JNIEnv *jni, jobject monitor) {
|
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);
|
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 Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
|
||||||
jint res;
|
jint res;
|
||||||
jvmtiError err;
|
jvmtiError err;
|
||||||
jvmtiCapabilities caps;
|
jvmtiCapabilities caps;
|
||||||
jvmtiEventCallbacks callbacks;
|
|
||||||
|
|
||||||
res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
|
res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
|
||||||
if (res != JNI_OK || jvmti == nullptr) {
|
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");
|
LOG("Warning: Monitor events are not implemented\n");
|
||||||
return JNI_ERR;
|
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;
|
return JNI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,41 +165,20 @@ Java_ObjectMonitorUsage_check(JNIEnv *jni, jclass cls, jobject obj, jthread owne
|
|||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_ObjectMonitorUsage_setTestedMonitor(JNIEnv *jni, jclass cls, jobject monitor) {
|
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) {
|
if (tested_monitor != nullptr) {
|
||||||
jni->DeleteGlobalRef(tested_monitor);
|
jni->DeleteGlobalRef(tested_monitor);
|
||||||
}
|
}
|
||||||
tested_monitor = (monitor != nullptr) ? jni->NewGlobalRef(monitor) : nullptr;
|
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
|
JNIEXPORT void JNICALL
|
||||||
Java_ObjectMonitorUsage_waitsToEnter(JNIEnv *jni, jclass cls) {
|
Java_ObjectMonitorUsage_ensureBlockedOnEnter(JNIEnv *jni, jclass cls, jthread thread) {
|
||||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
wait_for_state(jvmti, jni, thread, JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER);
|
||||||
return waits_to_enter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_ObjectMonitorUsage_waitsToBeNotified(JNIEnv *jni, jclass cls) {
|
Java_ObjectMonitorUsage_ensureWaitingToBeNotified(JNIEnv *jni, jclass cls, jthread thread) {
|
||||||
RawMonitorLocker rml(jvmti, jni, event_lock);
|
wait_for_state(jvmti, jni, thread, JVMTI_THREAD_STATE_WAITING_INDEFINITELY);
|
||||||
return waits_to_be_notified;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
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");
|
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.
|
// wait a second to give the breakpoints a chance to be hit.
|
||||||
#ifdef WINDOWS
|
sleep_sec(1);
|
||||||
Sleep(1000);
|
|
||||||
#else
|
|
||||||
sleep(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int idx = 0; idx < EXCLUDE_CNT; idx++) {
|
for (int idx = 0; idx < EXCLUDE_CNT; idx++) {
|
||||||
// Disable Breakpoint events on excluded thread
|
// Disable Breakpoint events on excluded thread
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
#define COMPLAIN LOG
|
#define COMPLAIN LOG
|
||||||
|
|
||||||
|
void sleep_ms(int millis);
|
||||||
const char* TranslateState(jint flags);
|
const char* TranslateState(jint flags);
|
||||||
const char* TranslateError(jvmtiError err);
|
const char* TranslateError(jvmtiError err);
|
||||||
|
|
||||||
@ -380,6 +380,24 @@ find_method(jvmtiEnv *jvmti, JNIEnv *jni, jclass klass, const char* mname) {
|
|||||||
return method;
|
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
|
#define MAX_FRAME_COUNT_PRINT_STACK_TRACE 200
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user