diff --git a/src/hotspot/share/prims/jvmti.xml b/src/hotspot/share/prims/jvmti.xml index add7d43ad3e..3bcf15466d7 100644 --- a/src/hotspot/share/prims/jvmti.xml +++ b/src/hotspot/share/prims/jvmti.xml @@ -8249,37 +8249,42 @@ class C2 extends C1 implements I2 { - The thread owning this monitor, or nullptr if unused + The platform thread owning this monitor, or nullptr if owned + by a virtual thread or not owned - The number of times the owning thread has entered the monitor + The number of times the platform thread owning this monitor has entered it, + or 0 if owned by a virtual thread or not owned - The number of threads waiting to own this monitor + The number of platform threads waiting to own this monitor, or 0 + if only virtual threads are waiting or no threads are waiting - The waiter_count waiting threads + The waiter_count waiting platform threads - The number of threads waiting to be notified by this monitor + The number of platform threads waiting to own this monitor, or 0 + if only virtual threads are waiting to be notified or no threads are waiting + to be notified - The notify_waiter_count threads waiting to be notified + The notify_waiter_count platform threads waiting to be notified @@ -8287,6 +8292,12 @@ class C2 extends C1 implements I2 { Get information about the object's monitor. The fields of the structure are filled in with information about usage of the monitor. +

+ This function does not support getting information about an object's monitor + when it is owned by a virtual thread. It also does not support returning a + reference to virtual threads that are waiting to own a monitor or waiting to + be notified. + Decide and then clarify suspend requirements. diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 1615e3c349c..de3d3f76528 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1482,14 +1482,19 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // first derive the object's owner and entry_count (if any) owning_thread = ObjectSynchronizer::get_lock_owner(tlh.list(), hobj); if (owning_thread != nullptr) { - Handle th(current_thread, get_vthread_or_thread_oop(owning_thread)); + oop thread_oop = get_vthread_or_thread_oop(owning_thread); + bool is_virtual = java_lang_VirtualThread::is_instance(thread_oop); + if (is_virtual) { + thread_oop = nullptr; + } + Handle th(current_thread, thread_oop); ret.owner = (jthread)jni_reference(calling_thread, th); // The recursions field of a monitor does not reflect recursions // as lightweight locks before inflating the monitor are not included. // We have to count the number of recursive monitor entries the hard way. // We pass a handle to survive any GCs along the way. - ret.entry_count = count_locked_objects(owning_thread, hobj); + ret.entry_count = is_virtual ? 0 : count_locked_objects(owning_thread, hobj); } // implied else: entry_count == 0 @@ -1513,6 +1518,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec // this object has a lightweight monitor } + jint skipped = 0; if (mon != nullptr) { // Robustness: the actual waiting list can be smaller. // The nWait count we got from the mon->waiters() may include the re-entering @@ -1522,11 +1528,16 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec for (ObjectWaiter* waiter = mon->first_waiter(); waiter != nullptr && (nWait == 0 || waiter != mon->first_waiter()); waiter = mon->next_waiter(waiter)) { + JavaThread *w = mon->thread_of_waiter(waiter); + oop thread_oop = get_vthread_or_thread_oop(w); + if (java_lang_VirtualThread::is_instance(thread_oop)) { + skipped++; + } nWait++; } } ret.waiter_count = nWant; - ret.notify_waiter_count = nWait; + ret.notify_waiter_count = nWait - skipped; // Allocate memory for heavyweight and lightweight monitor. jvmtiError err; @@ -1561,13 +1572,20 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec } if (ret.notify_waiter_count > 0) { // we have threads waiting to be notified in Object.wait() ObjectWaiter *waiter = mon->first_waiter(); + jint skipped = 0; for (int i = 0; i < nWait; i++) { JavaThread *w = mon->thread_of_waiter(waiter); + oop thread_oop = get_vthread_or_thread_oop(w); + bool is_virtual = java_lang_VirtualThread::is_instance(thread_oop); assert(w != nullptr, "sanity check"); - // If the thread was found on the ObjectWaiter list, then - // it has not been notified. - Handle th(current_thread, get_vthread_or_thread_oop(w)); - ret.notify_waiters[i] = (jthread)jni_reference(calling_thread, th); + if (java_lang_VirtualThread::is_instance(thread_oop)) { + skipped++; + } else { + // If the thread was found on the ObjectWaiter list, then + // it has not been notified. + Handle th(current_thread, get_vthread_or_thread_oop(w)); + ret.notify_waiters[i - skipped] = (jthread)jni_reference(calling_thread, th); + } waiter = mon->next_waiter(waiter); } } diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index b92e5a90c55..0e2edb7906b 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -1183,7 +1183,8 @@ void Threads::metadata_handles_do(void f(Metadata*)) { } #if INCLUDE_JVMTI -// Get count of Java threads that are waiting to enter or re-enter the specified monitor. +// Get Java threads that are waiting to enter or re-enter the specified monitor. +// Java threads that are executing mounted virtual threads are not included. GrowableArray* Threads::get_pending_threads(ThreadsList * t_list, int count, address monitor) { @@ -1194,14 +1195,16 @@ GrowableArray* Threads::get_pending_threads(ThreadsList * t_list, for (JavaThread* p : *t_list) { if (!p->can_call_java()) continue; + oop thread_oop = JvmtiEnvBase::get_vthread_or_thread_oop(p); + if (java_lang_VirtualThread::is_instance(thread_oop)) { + continue; + } // The first stage of async deflation does not affect any field // used by this comparison so the ObjectMonitor* is usable here. address pending = (address)p->current_pending_monitor(); address waiting = (address)p->current_waiting_monitor(); - oop thread_oop = JvmtiEnvBase::get_vthread_or_thread_oop(p); - bool is_virtual = java_lang_VirtualThread::is_instance(thread_oop); - jint state = is_virtual ? JvmtiEnvBase::get_vthread_state(thread_oop, p) - : JvmtiEnvBase::get_thread_state(thread_oop, p); + // do not include virtual threads to the list + jint state = JvmtiEnvBase::get_thread_state(thread_oop, p); if (pending == monitor || (waiting == monitor && (state & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER)) ) { // found a match diff --git a/src/hotspot/share/runtime/threads.hpp b/src/hotspot/share/runtime/threads.hpp index 6c4573827d9..39e307122c8 100644 --- a/src/hotspot/share/runtime/threads.hpp +++ b/src/hotspot/share/runtime/threads.hpp @@ -129,7 +129,8 @@ public: // Print threads busy compiling, and returns the number of printed threads. static unsigned print_threads_compiling(outputStream* st, char* buf, int buflen, bool short_form = false); - // Get count of Java threads that are waiting to enter or re-enter the specified monitor. + // Get Java threads that are waiting to enter or re-enter the specified monitor. + // Java threads that are executing mounted virtual threads are not included. static GrowableArray* get_pending_threads(ThreadsList * t_list, int count, address monitor); diff --git a/src/java.se/share/data/jdwp/jdwp.spec b/src/java.se/share/data/jdwp/jdwp.spec index df23a602b13..5206a0c6ae9 100644 --- a/src/java.se/share/data/jdwp/jdwp.spec +++ b/src/java.se/share/data/jdwp/jdwp.spec @@ -1617,11 +1617,14 @@ JDWP "Java(tm) Debug Wire Protocol" (object object "The object ID") ) (Reply - (threadObject owner "The monitor owner, or null if it is not currently owned.") - (int entryCount "The number of times the monitor has been entered.") - (Repeat waiters "The total number of threads that are waiting to enter or re-enter " - "the monitor, or waiting to be notified by the monitor." - (threadObject thread "A thread waiting for this monitor.") + (threadObject owner "The platform thread owning this monitor, or null " + "if owned by a virtual thread or not owned.") + (int entryCount "The number of times the owning platform thread has entered the monitor, " + "or 0 if owned by a virtual thread or not owned.") + (Repeat waiters "The total number of platform threads that are waiting to enter or re-enter " + "the monitor, or waiting to be notified by the monitor, or 0 if " + "only virtual threads are waiting or no threads are waiting." + (threadObject thread "A platform thread waiting for this monitor.") ) ) (ErrorSet @@ -2871,7 +2874,7 @@ JDWP "Java(tm) Debug Wire Protocol" "if not explicitly requested." (int requestID - "Request that generated event (or 0 if this " + "Request that generated event, or 0 if this " "event is automatically generated.") (threadObject thread "Initial thread") ) diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java b/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java index dbcf77d3e39..f53b8acbb8b 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java @@ -345,7 +345,7 @@ public interface ObjectReference extends Value { /** * Returns a List containing a {@link ThreadReference} for - * each thread currently waiting for this object's monitor. + * each platform thread currently waiting for this object's monitor. * See {@link ThreadReference#currentContendedMonitor} for * information about when a thread is considered to be waiting * for a monitor. @@ -355,7 +355,8 @@ public interface ObjectReference extends Value { * operation is supported. * * @return a List of {@link ThreadReference} objects. The list - * has zero length if no threads are waiting for the monitor. + * has zero length if no threads are waiting for the monitor, + * or only virtual threads are waiting for the monitor. * @throws java.lang.UnsupportedOperationException if the * target VM does not support this operation. * @throws IncompatibleThreadStateException if any @@ -366,7 +367,7 @@ public interface ObjectReference extends Value { throws IncompatibleThreadStateException; /** - * Returns an {@link ThreadReference} for the thread, if any, + * Returns a {@link ThreadReference} for the platform thread, if any, * which currently owns this object's monitor. * See {@link ThreadReference#ownedMonitors} for a definition * of ownership. @@ -375,8 +376,9 @@ public interface ObjectReference extends Value { * {@link VirtualMachine#canGetMonitorInfo} to determine if the * operation is supported. * - * @return the {@link ThreadReference} which currently owns the - * monitor, or null if it is unowned. + * @return the {@link ThreadReference} of the platform thread which + * currently owns the monitor, or null if the monitor is owned + * by a virtual thread or not owned. * * @throws java.lang.UnsupportedOperationException if the * target VM does not support this operation. @@ -386,8 +388,9 @@ public interface ObjectReference extends Value { ThreadReference owningThread() throws IncompatibleThreadStateException; /** - * Returns the number times this object's monitor has been - * entered by the current owning thread. + * Returns the number of times this object's monitor has been entered by + * the current owning thread if the owning thread is platform thread; + * Returns 0 if not owned by a platform thread. * See {@link ThreadReference#ownedMonitors} for a definition * of ownership. *

diff --git a/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java b/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java index bc9a0c5cabc..0d136cadef7 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java +++ b/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java @@ -114,6 +114,13 @@ public class ObjectMonitorUsage { throw new Error("Unexpected " + e); } } + static Thread expOwnerThread() { + return Thread.currentThread().isVirtual() ? null : Thread.currentThread(); + } + + static int expEntryCount() { + return Thread.currentThread().isVirtual() ? 0 : 1; + } /* Scenario #0: * - owning: 0 @@ -127,14 +134,18 @@ public class ObjectMonitorUsage { setTestedMonitor(lockCheck); Thread[] wThreads = startWaitingThreads(isVirtual); + final int expWaitingCount = isVirtual ? 0 : NUMBER_OF_WAITING_THREADS; + // The numbers below describe the testing scenario, not the expected results. + // The expected numbers are different for virtual threads because + // they are not supported by JVMTI GetObjectMonitorUsage. // entry count: 0 // count of threads waiting to enter: 0 // count of threads waiting to re-enter: 0 // count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS check(lockCheck, null, 0, // no owner thread 0, // count of threads waiting to enter: 0 - NUMBER_OF_WAITING_THREADS); + expWaitingCount); synchronized (lockCheck) { lockCheck.notifyAll(); @@ -158,20 +169,30 @@ public class ObjectMonitorUsage { Thread[] eThreads = null; synchronized (lockCheck) { + // Virtual threads are not supported by GetObjectMonitorUsage. + // Correct the expected values for the virtual thread case. + int expEnteringCount = isVirtual ? 0 : NUMBER_OF_ENTERING_THREADS; + + // The numbers below describe the testing scenario, not the expected results. + // The expected numbers are different for virtual threads because + // they are not supported by JVMTI GetObjectMonitorUsage. // entry count: 1 // count of threads waiting to enter: 0 // count of threads waiting to re-enter: 0 // count of threads waiting to be notified: 0 - check(lockCheck, Thread.currentThread(), 1, 0, 0); + check(lockCheck, expOwnerThread(), expEntryCount(), 0, 0); eThreads = startEnteringThreads(isVirtual); + // The numbers below describe the testing scenario, not the expected results. + // The expected numbers are different for virtual threads because + // they are not supported by JVMTI GetObjectMonitorUsage. // entry count: 1 // count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS // count of threads waiting to re-enter: 0 // count of threads waiting to be notified: 0 - check(lockCheck, Thread.currentThread(), 1, - NUMBER_OF_ENTERING_THREADS, + check(lockCheck, expOwnerThread(), expEntryCount(), + expEnteringCount, 0 /* count of threads waiting to be notified: 0 */); } @@ -195,15 +216,23 @@ public class ObjectMonitorUsage { Thread[] eThreads = null; synchronized (lockCheck) { + // Virtual threads are not supported by the GetObjectMonitorUsage. + // Correct the expected values for the virtual thread case. + int expEnteringCount = isVirtual ? 0 : NUMBER_OF_ENTERING_THREADS; + int expWaitingCount = isVirtual ? 0 : NUMBER_OF_WAITING_THREADS; + eThreads = startEnteringThreads(isVirtual); + // The numbers below describe the testing scenario, not the expected results. + // The expected numbers are different for virtual threads because + // they are not supported by JVMTI GetObjectMonitorUsage. // entry count: 1 // count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS // count of threads waiting to re-enter: 0 // count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS - check(lockCheck, Thread.currentThread(), 1, - NUMBER_OF_ENTERING_THREADS, - NUMBER_OF_WAITING_THREADS); + check(lockCheck, expOwnerThread(), expEntryCount(), + expEnteringCount, + expWaitingCount); lockCheck.notifyAll(); } @@ -234,35 +263,51 @@ public class ObjectMonitorUsage { Thread[] eThreads = null; synchronized (lockCheck) { + // Virtual threads are not supported by GetObjectMonitorUsage. + // Correct the expected values for the virtual thread case. + int expEnteringCount = isVirtual ? 0 : NUMBER_OF_ENTERING_THREADS; + int expWaitingCount = isVirtual ? 0 : NUMBER_OF_WAITING_THREADS; + + // The numbers below describe the testing scenario, not the expected results. + // The expected numbers are different for virtual threads because + // they are not supported by JVMTI GetObjectMonitorUsage. // entry count: 1 // count of threads waiting to enter: 0 // count of threads waiting to re-enter: 0 // count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS - check(lockCheck, Thread.currentThread(), 1, + check(lockCheck, expOwnerThread(), expEntryCount(), 0, // number of threads waiting to enter or re-enter - NUMBER_OF_WAITING_THREADS); + expWaitingCount); eThreads = startEnteringThreads(isVirtual); + // The numbers below describe the testing scenario, not the expected results. + // The expected numbers are different for virtual threads because + // they are not supported by JVMTI GetObjectMonitorUsage. // entry count: 1 // count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS // count of threads waiting to re-enter: 0 // count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS - check(lockCheck, Thread.currentThread(), 1, - NUMBER_OF_ENTERING_THREADS, - NUMBER_OF_WAITING_THREADS); + check(lockCheck, expOwnerThread(), expEntryCount(), + expEnteringCount, + expWaitingCount); for (int i = 0; i < NUMBER_OF_WAITING_THREADS; i++) { + expEnteringCount = isVirtual ? 0 : NUMBER_OF_ENTERING_THREADS + i + 1; + expWaitingCount = isVirtual ? 0 : NUMBER_OF_WAITING_THREADS - i - 1; lockCheck.notify(); // notify waiting threads one by one // now the notified WaitingTask has to be blocked on the lockCheck re-enter + // The numbers below describe the testing scenario, not the expected results. + // The expected numbers are different for virtual threads because + // they are not supported by JVMTI GetObjectMonitorUsage. // entry count: 1 // count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS // count of threads waiting to re-enter: i + 1 // count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS - i - 1 - check(lockCheck, Thread.currentThread(), 1, - NUMBER_OF_ENTERING_THREADS + i + 1, - NUMBER_OF_WAITING_THREADS - i - 1); + check(lockCheck, expOwnerThread(), expEntryCount(), + expEnteringCount, + expWaitingCount); } } joinThreads(wThreads); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002.java index 7736eae1d2b..e5e8f4e8d80 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/entryCount/entrycount002.java @@ -197,8 +197,11 @@ public class entrycount002 { display("Checking entryCount for iteration : " + i); try { + // The lockRef.entryCount() is expected to return 0 if the owner thread is virtual. + int expEntryCount = mainThread.isVirtual() ? 0 : i; int entryCount = lockRef.entryCount(); - if (entryCount != i) { + + if (entryCount != expEntryCount) { exitCode = Consts.TEST_FAILED; complain("entry count method returned unexpected value : " + entryCount + "\n\t expected one : " + i); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002.java index 89d1b703310..83e0bbb8c05 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/owningThread/owningthread002.java @@ -200,6 +200,15 @@ public class owningthread002 { try { ThreadReference thread = lockRef.owningThread(); + // The lockRef.owningThread() is expected to return null if tested threads are virtual. + if (eventThread.isVirtual()) { + if (thread == null) { + display("expected null is returned` by owningThread method on virtual thread: " + eventThread.name()); + } else { + complain("owningThread returned ThreadReference of virtual thread instead of null: " + thread.name()); + } + continue; + } if (thread.name().indexOf(owningthread002a.threadNamePrefix) < 0) { exitCode = Consts.TEST_FAILED; complain("owningThread returned ThreadReference with unexpected name: " + thread.name()); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002.java index 356f78876aa..74bc41a34eb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/waitingThreads/waitingthreads002.java @@ -122,6 +122,9 @@ public class waitingthreads002 { if (thread.name().indexOf(waitingthreads002a.threadNamePrefix) >= 0 && thread.status() == ThreadReference.THREAD_STATUS_MONITOR ) { waitingCount++; + // Virtual threads are not present in result returned by objRef.waitingThreads(). + if (!thread.isVirtual()) { + } } } } @@ -159,7 +162,9 @@ public class waitingthreads002 { objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName)); try { List waitingThreads = objRef.waitingThreads(); - if (waitingThreads.size() != waitingthreads002a.threadCount) { + final boolean vthreadMode = "Virtual".equals(System.getProperty("test.thread.factory")); + final int expWaitingCount = vthreadMode ? 0 : waitingthreads002a.threadCount; + if (waitingThreads.size() != expWaitingCount) { exitStatus = Consts.TEST_FAILED; complain("waitingThreads method returned list with unexpected size for " + fieldName + "\n\t expected value : " + waitingthreads002a.threadCount + "; got one : " + waitingThreads.size()); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage001.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage001.java index 1ae3bf79e1c..c3c3cb31ebd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage001.java @@ -61,8 +61,16 @@ public class objmonusage001 { syncObject[i] = new Object(); runn[i] = new objmonusage001a(mainThread, i, syncObject[i]); } + // Virtual threads are not supported by GetObjectMonitorUsage. + // Correct the expected values if the test is executed with + // JTREG_TEST_THREAD_FACTORY=Virtual. + Thread expOwner = mainThread.isVirtual() ? null : mainThread; + int expEntryCount = mainThread.isVirtual() ? 0 : 1; for (int i = 0; i < NUMBER_OF_THREADS; i++) { + Thread expNotifyWaiter = runn[i].isVirtual() ? null : runn[i]; + int expNotifyWaitingCount = runn[i].isVirtual() ? 0 : 1; + synchronized (syncObject[i]) { runn[i].start(); try { @@ -92,8 +100,8 @@ public class objmonusage001 { // This is a stable verification point because the worker thread is in wait() // and is not notified and the main thread is doing the verification. // - check(NUMBER_OF_THREADS + i, syncObject[i], mainThread, 1, - null, 0, runn[i], 1); + check(NUMBER_OF_THREADS + i, syncObject[i], expOwner, expEntryCount, + null, 0, expNotifyWaiter, expNotifyWaitingCount); } // Check #3: @@ -117,7 +125,7 @@ public class objmonusage001 { // and is not notified and the main thread is doing the verification. // check((NUMBER_OF_THREADS * 2) + i, syncObject[i], null, 0, - null, 0, runn[i], 1); + null, 0, expNotifyWaiter, expNotifyWaitingCount); } for (int i = 0; i < NUMBER_OF_THREADS; i++) { @@ -147,6 +155,14 @@ class objmonusage001a extends Thread { } public void run() { + // Virtual threads are not supported by GetObjectMonitorUsage. + // Correct the expected values if the test is executed with + // JTREG_TEST_THREAD_FACTORY=Virtual. + Thread expOwner = this.isVirtual() ? null : this; + Thread expNotifyWaiter = mainThread.isVirtual() ? null : mainThread; + int expEntryCount = this.isVirtual() ? 0 : 1; + int expNotifyWaitingCount = mainThread.isVirtual() ? 0 : 1; + synchronized (syncObject) { // Check #1: // - owner == this_thread: @@ -166,8 +182,8 @@ class objmonusage001a extends Thread { // This is a stable verification point because the main thread is in wait() // and is not notified and this worker thread is doing the verification. // - objmonusage001.check(index, syncObject, this, 1, - null, 0, mainThread, 1); + objmonusage001.check(index, syncObject, expOwner, expEntryCount, + null, 0, expNotifyWaiter, expNotifyWaitingCount); syncObject.notify(); try { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage004.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage004.java index 37addef82d6..8d79a6011f5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,11 +60,23 @@ public class objmonusage004 { Thread currThread = Thread.currentThread(); ContendThread thr[] = new ContendThread[NUMBER_OF_THREADS]; synchronized (lockCheck) { + // Virtual threads are not supported by GetObjectMonitorUsage. + // Correct the expected values if the test is executed with + // JTREG_TEST_THREAD_FACTORY=Virtual. + Thread expOwner = currThread.isVirtual() ? null : currThread; + int expEntryCount = currThread.isVirtual() ? 0 : 2; + synchronized (lockCheck) { - check(lockCheck, currThread, 2, 0); + check(lockCheck, expOwner, expEntryCount, 0); } + expEntryCount = currThread.isVirtual() ? 0 : 1; + int expWaiterCount = 0; + for (int i = 0; i < NUMBER_OF_THREADS; i++) { thr[i] = new ContendThread(); + if (!thr[i].isVirtual()) { + expWaiterCount++; + } synchronized (lockStart) { thr[i].start(); try { @@ -74,7 +86,7 @@ public class objmonusage004 { throw new Error("Unexpected " + e); } } - check(lockCheck, currThread, 1, i + 1); + check(lockCheck, expOwner, expEntryCount, expWaiterCount); } }