7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package java.lang;
26
27 import java.util.Arrays;
28 import java.util.Locale;
29 import java.util.Objects;
30 import java.util.concurrent.CountDownLatch;
31 import java.util.concurrent.Executor;
32 import java.util.concurrent.Executors;
33 import java.util.concurrent.ForkJoinPool;
34 import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
35 import java.util.concurrent.ForkJoinTask;
36 import java.util.concurrent.Future;
37 import java.util.concurrent.RejectedExecutionException;
38 import java.util.concurrent.ScheduledExecutorService;
39 import java.util.concurrent.ScheduledThreadPoolExecutor;
40 import java.util.concurrent.TimeUnit;
41 import java.util.stream.Stream;
42 import jdk.internal.event.VirtualThreadEndEvent;
43 import jdk.internal.event.VirtualThreadStartEvent;
44 import jdk.internal.event.VirtualThreadSubmitFailedEvent;
45 import jdk.internal.misc.CarrierThread;
46 import jdk.internal.misc.InnocuousThread;
48 import jdk.internal.vm.Continuation;
49 import jdk.internal.vm.ContinuationScope;
50 import jdk.internal.vm.StackableScope;
51 import jdk.internal.vm.ThreadContainer;
52 import jdk.internal.vm.ThreadContainers;
53 import jdk.internal.vm.annotation.ChangesCurrentThread;
54 import jdk.internal.vm.annotation.Hidden;
55 import jdk.internal.vm.annotation.IntrinsicCandidate;
56 import jdk.internal.vm.annotation.JvmtiHideEvents;
57 import jdk.internal.vm.annotation.JvmtiMountTransition;
58 import jdk.internal.vm.annotation.ReservedStackAccess;
59 import sun.nio.ch.Interruptible;
60 import static java.util.concurrent.TimeUnit.*;
61
62 /**
63 * A thread that is scheduled by the Java virtual machine rather than the operating system.
64 */
65 final class VirtualThread extends BaseVirtualThread {
66 private static final Unsafe U = Unsafe.getUnsafe();
67 private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
68 private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler();
69 private static final ScheduledExecutorService[] DELAYED_TASK_SCHEDULERS = createDelayedTaskSchedulers();
70
71 private static final long STATE = U.objectFieldOffset(VirtualThread.class, "state");
72 private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit");
73 private static final long CARRIER_THREAD = U.objectFieldOffset(VirtualThread.class, "carrierThread");
74 private static final long TERMINATION = U.objectFieldOffset(VirtualThread.class, "termination");
75 private static final long ON_WAITING_LIST = U.objectFieldOffset(VirtualThread.class, "onWaitingList");
76
77 // scheduler and continuation
78 private final Executor scheduler;
79 private final Continuation cont;
80 private final Runnable runContinuation;
81
82 // virtual thread state, accessed by VM
83 private volatile int state;
84
85 /*
86 * Virtual thread state transitions:
87 *
88 * NEW -> STARTED // Thread.start, schedule to run
1393
1394 @IntrinsicCandidate
1395 @JvmtiMountTransition
1396 private native void notifyJvmtiMount(boolean hide);
1397
1398 @IntrinsicCandidate
1399 @JvmtiMountTransition
1400 private native void notifyJvmtiUnmount(boolean hide);
1401
1402 @IntrinsicCandidate
1403 private static native void notifyJvmtiDisableSuspend(boolean enter);
1404
1405 private static native void registerNatives();
1406 static {
1407 registerNatives();
1408
1409 // ensure VTHREAD_GROUP is created, may be accessed by JVMTI
1410 var group = Thread.virtualThreadGroup();
1411 }
1412
1413 /**
1414 * Creates the default ForkJoinPool scheduler.
1415 */
1416 private static ForkJoinPool createDefaultScheduler() {
1417 ForkJoinWorkerThreadFactory factory = pool -> new CarrierThread(pool);
1418 int parallelism, maxPoolSize, minRunnable;
1419 String parallelismValue = System.getProperty("jdk.virtualThreadScheduler.parallelism");
1420 String maxPoolSizeValue = System.getProperty("jdk.virtualThreadScheduler.maxPoolSize");
1421 String minRunnableValue = System.getProperty("jdk.virtualThreadScheduler.minRunnable");
1422 if (parallelismValue != null) {
1423 parallelism = Integer.parseInt(parallelismValue);
1424 } else {
1425 parallelism = Runtime.getRuntime().availableProcessors();
1426 }
1427 if (maxPoolSizeValue != null) {
1428 maxPoolSize = Integer.parseInt(maxPoolSizeValue);
1429 parallelism = Integer.min(parallelism, maxPoolSize);
1430 } else {
1431 maxPoolSize = Integer.max(parallelism, 256);
1432 }
1433 if (minRunnableValue != null) {
1434 minRunnable = Integer.parseInt(minRunnableValue);
1435 } else {
1436 minRunnable = Integer.max(parallelism / 2, 1);
|
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package java.lang;
26
27 import java.lang.reflect.Constructor;
28 import java.util.Arrays;
29 import java.util.Locale;
30 import java.util.Objects;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.Executor;
33 import java.util.concurrent.Executors;
34 import java.util.concurrent.ForkJoinPool;
35 import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
36 import java.util.concurrent.ForkJoinTask;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.RejectedExecutionException;
39 import java.util.concurrent.ScheduledExecutorService;
40 import java.util.concurrent.ScheduledThreadPoolExecutor;
41 import java.util.concurrent.TimeUnit;
42 import java.util.stream.Stream;
43 import jdk.internal.event.VirtualThreadEndEvent;
44 import jdk.internal.event.VirtualThreadStartEvent;
45 import jdk.internal.event.VirtualThreadSubmitFailedEvent;
46 import jdk.internal.misc.CarrierThread;
47 import jdk.internal.misc.InnocuousThread;
49 import jdk.internal.vm.Continuation;
50 import jdk.internal.vm.ContinuationScope;
51 import jdk.internal.vm.StackableScope;
52 import jdk.internal.vm.ThreadContainer;
53 import jdk.internal.vm.ThreadContainers;
54 import jdk.internal.vm.annotation.ChangesCurrentThread;
55 import jdk.internal.vm.annotation.Hidden;
56 import jdk.internal.vm.annotation.IntrinsicCandidate;
57 import jdk.internal.vm.annotation.JvmtiHideEvents;
58 import jdk.internal.vm.annotation.JvmtiMountTransition;
59 import jdk.internal.vm.annotation.ReservedStackAccess;
60 import sun.nio.ch.Interruptible;
61 import static java.util.concurrent.TimeUnit.*;
62
63 /**
64 * A thread that is scheduled by the Java virtual machine rather than the operating system.
65 */
66 final class VirtualThread extends BaseVirtualThread {
67 private static final Unsafe U = Unsafe.getUnsafe();
68 private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
69 private static final Executor DEFAULT_SCHEDULER = createDefaultScheduler();
70 private static final ScheduledExecutorService[] DELAYED_TASK_SCHEDULERS = createDelayedTaskSchedulers();
71
72 private static final long STATE = U.objectFieldOffset(VirtualThread.class, "state");
73 private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit");
74 private static final long CARRIER_THREAD = U.objectFieldOffset(VirtualThread.class, "carrierThread");
75 private static final long TERMINATION = U.objectFieldOffset(VirtualThread.class, "termination");
76 private static final long ON_WAITING_LIST = U.objectFieldOffset(VirtualThread.class, "onWaitingList");
77
78 // scheduler and continuation
79 private final Executor scheduler;
80 private final Continuation cont;
81 private final Runnable runContinuation;
82
83 // virtual thread state, accessed by VM
84 private volatile int state;
85
86 /*
87 * Virtual thread state transitions:
88 *
89 * NEW -> STARTED // Thread.start, schedule to run
1394
1395 @IntrinsicCandidate
1396 @JvmtiMountTransition
1397 private native void notifyJvmtiMount(boolean hide);
1398
1399 @IntrinsicCandidate
1400 @JvmtiMountTransition
1401 private native void notifyJvmtiUnmount(boolean hide);
1402
1403 @IntrinsicCandidate
1404 private static native void notifyJvmtiDisableSuspend(boolean enter);
1405
1406 private static native void registerNatives();
1407 static {
1408 registerNatives();
1409
1410 // ensure VTHREAD_GROUP is created, may be accessed by JVMTI
1411 var group = Thread.virtualThreadGroup();
1412 }
1413
1414 /**
1415 * Creates the default scheduler.
1416 * If the system property {@code jdk.virtualThreadScheduler.implClass} is set then
1417 * its value is the name of a class that implements java.util.concurrent.Executor.
1418 * The class is public in an exported package, has a public no-arg constructor,
1419 * and is visible to the system class loader.
1420 * If the system property is not set then the default scheduler will be a
1421 * ForkJoinPool instance.
1422 */
1423 private static Executor createDefaultScheduler() {
1424 String propValue = System.getProperty("jdk.virtualThreadScheduler.implClass");
1425 if (propValue != null) {
1426 try {
1427 Class<?> clazz = Class.forName(propValue, true,
1428 ClassLoader.getSystemClassLoader());
1429 Constructor<?> ctor = clazz.getConstructor();
1430 var scheduler = (Executor) ctor.newInstance();
1431 System.err.println("""
1432 WARNING: Using custom scheduler, this is an experimental feature.""");
1433 return scheduler;
1434 } catch (Exception ex) {
1435 throw new Error(ex);
1436 }
1437 } else {
1438 return createDefaultForkJoinPoolScheduler();
1439 }
1440 }
1441
1442 /**
1443 * Creates the default ForkJoinPool scheduler.
1444 */
1445 private static ForkJoinPool createDefaultForkJoinPoolScheduler() {
1446 ForkJoinWorkerThreadFactory factory = pool -> new CarrierThread(pool);
1447 int parallelism, maxPoolSize, minRunnable;
1448 String parallelismValue = System.getProperty("jdk.virtualThreadScheduler.parallelism");
1449 String maxPoolSizeValue = System.getProperty("jdk.virtualThreadScheduler.maxPoolSize");
1450 String minRunnableValue = System.getProperty("jdk.virtualThreadScheduler.minRunnable");
1451 if (parallelismValue != null) {
1452 parallelism = Integer.parseInt(parallelismValue);
1453 } else {
1454 parallelism = Runtime.getRuntime().availableProcessors();
1455 }
1456 if (maxPoolSizeValue != null) {
1457 maxPoolSize = Integer.parseInt(maxPoolSizeValue);
1458 parallelism = Integer.min(parallelism, maxPoolSize);
1459 } else {
1460 maxPoolSize = Integer.max(parallelism, 256);
1461 }
1462 if (minRunnableValue != null) {
1463 minRunnable = Integer.parseInt(minRunnableValue);
1464 } else {
1465 minRunnable = Integer.max(parallelism / 2, 1);
|