< prev index next > test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java
Print this page
*/
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
+ import jdk.test.lib.thread.VThreadScheduler;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
public static void main(String[] args) throws Exception {
String test = args[0];
String[] cmdArgs = new String[] {
"-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
! // Grant access to ThreadBuilders$VirtualThreadBuilder
"--add-opens=java.base/java.lang=ALL-UNNAMED",
// Enable the JNI warning
"-Xcheck:jni",
"-Xlog:jni=debug",
// Enable thread termination logging as a visual cross-check
public static void main(String[] args) throws Exception {
String test = args[0];
String[] cmdArgs = new String[] {
"-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
! // Need to open java.lang to use VThreadScheduler.virtualThreadBuilder
"--add-opens=java.base/java.lang=ALL-UNNAMED",
// Enable the JNI warning
"-Xcheck:jni",
"-Xlog:jni=debug",
// Enable thread termination logging as a visual cross-check
static {
System.loadLibrary("JNIMonitor");
}
- // This gives us a way to control the scheduler used for our virtual threads. The test
- // only works as intended when the virtual threads run on the same carrier thread (as
- // that carrier maintains ownership of the monitor if the virtual thread fails to unlock it).
- // The original issue was also only discovered due to the carrier thread terminating
- // unexpectedly, so we can force that condition too by shutting down our custom scheduler.
- private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
- Thread.Builder.OfVirtual builder = Thread.ofVirtual();
- try {
- Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
- Constructor<?> ctor = clazz.getDeclaredConstructor(Executor.class);
- ctor.setAccessible(true);
- return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler);
- } catch (InvocationTargetException e) {
- Throwable cause = e.getCause();
- if (cause instanceof RuntimeException re) {
- throw re;
- }
- throw new RuntimeException(e);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable {
final Object[] monitors = new Object[nThreads];
for (int i = 0; i < nThreads; i++) {
monitors[i] = new Object();
}
final AtomicReference<Throwable> exception = new AtomicReference();
// Ensure all our VT's operate of the same carrier, sequentially.
ExecutorService scheduler = Executors.newSingleThreadExecutor();
! ThreadFactory factory = virtualThreadBuilder(scheduler).factory();
for (int i = 0 ; i < nThreads; i++) {
Object monitor = skipUnlock ? monitors[i] : monitors[0];
Thread th = factory.newThread(() -> {
try {
int res = monitorEnter(monitor);
static {
System.loadLibrary("JNIMonitor");
}
static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable {
final Object[] monitors = new Object[nThreads];
for (int i = 0; i < nThreads; i++) {
monitors[i] = new Object();
}
final AtomicReference<Throwable> exception = new AtomicReference();
// Ensure all our VT's operate of the same carrier, sequentially.
+ // This gives us a way to control the scheduler used for our virtual threads. The test
+ // only works as intended when the virtual threads run on the same carrier thread (as
+ // that carrier maintains ownership of the monitor if the virtual thread fails to unlock it).
+ // The original issue was also only discovered due to the carrier thread terminating
+ // unexpectedly, so we can force that condition too by shutting down our custom scheduler.
ExecutorService scheduler = Executors.newSingleThreadExecutor();
! ThreadFactory factory = VThreadScheduler.virtualThreadBuilder(scheduler).factory();
for (int i = 0 ; i < nThreads; i++) {
Object monitor = skipUnlock ? monitors[i] : monitors[0];
Thread th = factory.newThread(() -> {
try {
int res = monitorEnter(monitor);
< prev index next >