1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 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 com.sun.management.internal; 26 27 import java.util.concurrent.ForkJoinPool; 28 import javax.management.ObjectName; 29 import jdk.management.VirtualThreadSchedulerMXBean; 30 import jdk.internal.access.SharedSecrets; 31 import jdk.internal.vm.ContinuationSupport; 32 import sun.management.Util; 33 34 /** 35 * Provides the implementation of the management interface for the JDK's default virtual 36 * thread scheduler. 37 */ 38 public class VirtualThreadSchedulerImpls { 39 private VirtualThreadSchedulerImpls() { 40 } 41 42 public static VirtualThreadSchedulerMXBean create() { 43 if (ContinuationSupport.isSupported()) { 44 return new VirtualThreadSchedulerImpl(); 45 } else { 46 return new BoundVirtualThreadSchedulerImpl(); 47 } 48 } 49 50 /** 51 * Base implementation of VirtualThreadSchedulerMXBean. 52 */ 53 private abstract static class BaseVirtualThreadSchedulerImpl 54 implements VirtualThreadSchedulerMXBean { 55 56 @Override 57 public final ObjectName getObjectName() { 58 return Util.newObjectName("jdk.management:type=VirtualThreadScheduler"); 59 } 60 61 @Override 62 public String toString() { 63 var sb = new StringBuilder("[parallelism="); 64 sb.append(getParallelism()); 65 append(sb, "size", getPoolSize()); 66 append(sb, "mounted", getMountedVirtualThreadCount()); 67 append(sb, "queued", getQueuedVirtualThreadCount()); 68 sb.append(']'); 69 return sb.toString(); 70 } 71 72 private void append(StringBuilder sb, String name, long value) { 73 sb.append(", ").append(name).append('='); 74 if (value >= 0) { 75 sb.append(value); 76 } else { 77 sb.append("<unavailable>"); 78 } 79 } 80 } 81 82 /** 83 * Implementation of VirtualThreadSchedulerMXBean when virtual threads are 84 * implemented with continuations + scheduler. 85 */ 86 private static final class VirtualThreadSchedulerImpl extends BaseVirtualThreadSchedulerImpl { 87 /** 88 * Holder class for scheduler. 89 */ 90 private static class Scheduler { 91 private static final Thread.VirtualThreadScheduler SCHEDULER = 92 SharedSecrets.getJavaLangAccess().defaultVirtualThreadScheduler(); 93 static Thread.VirtualThreadScheduler instance() { 94 return SCHEDULER; 95 } 96 } 97 98 @Override 99 public int getParallelism() { 100 if (Scheduler.instance() instanceof ForkJoinPool pool) { 101 return pool.getParallelism(); 102 } 103 return -1; // unknown 104 } 105 106 @Override 107 public void setParallelism(int size) { 108 if (Scheduler.instance() instanceof ForkJoinPool pool) { 109 pool.setParallelism(size); 110 if (pool.getPoolSize() < size) { 111 // FJ worker thread creation is on-demand 112 Thread.startVirtualThread(() -> { }); 113 } 114 return; 115 } 116 throw new UnsupportedOperationException(); 117 } 118 119 @Override 120 public int getPoolSize() { 121 if (Scheduler.instance() instanceof ForkJoinPool pool) { 122 return pool.getPoolSize(); 123 } 124 return -1; // unknown 125 } 126 127 @Override 128 public int getMountedVirtualThreadCount() { 129 if (Scheduler.instance() instanceof ForkJoinPool pool) { 130 return pool.getActiveThreadCount(); 131 } 132 return -1; // unknown 133 } 134 135 @Override 136 public long getQueuedVirtualThreadCount() { 137 if (Scheduler.instance() instanceof ForkJoinPool pool) { 138 return pool.getQueuedTaskCount() + pool.getQueuedSubmissionCount(); 139 } 140 return -1L; // unknown 141 } 142 } 143 144 /** 145 * Implementation of VirtualThreadSchedulerMXBean when virtual threads are backed 146 * by platform threads. 147 */ 148 private static final class BoundVirtualThreadSchedulerImpl extends BaseVirtualThreadSchedulerImpl { 149 @Override 150 public int getParallelism() { 151 return Integer.MAX_VALUE; 152 } 153 154 @Override 155 public void setParallelism(int size) { 156 throw new UnsupportedOperationException(); 157 } 158 159 @Override 160 public int getPoolSize() { 161 return -1; 162 } 163 164 @Override 165 public int getMountedVirtualThreadCount() { 166 return -1; 167 } 168 169 @Override 170 public long getQueuedVirtualThreadCount() { 171 return -1L; 172 } 173 } 174 } 175