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 java.util.concurrent.ThreadPoolExecutor; 29 import javax.management.ObjectName; 30 import jdk.management.VirtualThreadSchedulerMXBean; 31 import jdk.internal.access.JavaLangAccess; 32 import jdk.internal.access.SharedSecrets; 33 import jdk.internal.vm.ContinuationSupport; 34 import sun.management.Util; 35 36 /** 37 * Provides the implementation of the management interface for the JDK's virtual thread scheduler. 38 */ 39 public class VirtualThreadSchedulerImpls { 40 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); 41 42 private VirtualThreadSchedulerImpls() { 43 } 44 45 /** 46 * Creates the VirtualThreadSchedulerMXBean. 47 */ 48 public static VirtualThreadSchedulerMXBean create() { 49 // -XX:-VMContinuations 50 if (!ContinuationSupport.isSupported()) { 51 return new BoundVirtualThreadSchedulerImpl(); 52 } 53 54 // built-in scheduler 55 if (System.getProperty("jdk.virtualThreadScheduler.implClass") == null) { 56 return new BuiltinVirtualThreadSchedulerImpl(); 57 } 58 59 // custom scheduler implements VirtualThreadSchedulerMXBean 60 if (JLA.defaultVirtualThreadScheduler() instanceof VirtualThreadSchedulerMXBean bean) { 61 return bean; 62 } 63 64 // custom scheduler does not implement VirtualThreadSchedulerMXBean 65 return new CustomVirtualThreadSchedulerImpl(); 66 } 67 68 /** 69 * Base implementation of VirtualThreadSchedulerMXBean. 70 */ 71 private abstract static class BaseVirtualThreadSchedulerImpl 72 implements VirtualThreadSchedulerMXBean { 73 74 @Override 75 public final ObjectName getObjectName() { 76 return Util.newObjectName("jdk.management:type=VirtualThreadScheduler"); 77 } 78 79 @Override 80 public String toString() { 81 var sb = new StringBuilder("[parallelism="); 82 sb.append(getParallelism()); 83 append(sb, "size", getPoolSize()); 84 append(sb, "mounted", getMountedVirtualThreadCount()); 85 append(sb, "queued", getQueuedVirtualThreadCount()); 86 sb.append(']'); 87 return sb.toString(); 88 } 89 90 private void append(StringBuilder sb, String name, long value) { 91 sb.append(", ").append(name).append('='); 92 if (value >= 0) { 93 sb.append(value); 94 } else { 95 sb.append("<unavailable>"); 96 } 97 } 98 } 99 100 /** 101 * Implementation of VirtualThreadSchedulerMXBean when virtual threads are 102 * implemented with continuations and the built-in scheduler. 103 */ 104 private static final class BuiltinVirtualThreadSchedulerImpl 105 extends BaseVirtualThreadSchedulerImpl { 106 107 private Thread.VirtualThreadScheduler builtinScheduler() { 108 return JLA.builtinVirtualThreadScheduler(); 109 } 110 111 @Override 112 public int getParallelism() { 113 return switch (builtinScheduler()) { 114 case ForkJoinPool pool -> pool.getParallelism(); 115 case ThreadPoolExecutor pool -> pool.getMaximumPoolSize(); 116 default -> -1; 117 }; 118 } 119 120 @Override 121 public void setParallelism(int size) { 122 if (builtinScheduler() instanceof ForkJoinPool pool) { 123 pool.setParallelism(size); 124 } else { 125 throw new UnsupportedOperationException(); 126 } 127 } 128 129 @Override 130 public int getPoolSize() { 131 return switch (builtinScheduler()) { 132 case ForkJoinPool pool -> pool.getPoolSize(); 133 case ThreadPoolExecutor pool -> pool.getPoolSize(); 134 default -> -1; 135 }; 136 } 137 138 @Override 139 public int getMountedVirtualThreadCount() { 140 return switch (builtinScheduler()) { 141 case ForkJoinPool pool -> pool.getActiveThreadCount(); 142 case ThreadPoolExecutor pool -> pool.getActiveCount(); 143 default -> -1; 144 }; 145 } 146 147 @Override 148 public long getQueuedVirtualThreadCount() { 149 return switch (builtinScheduler()) { 150 case ForkJoinPool pool -> pool.getQueuedTaskCount() + pool.getQueuedSubmissionCount(); 151 case ThreadPoolExecutor pool -> pool.getQueue().size(); 152 default -> -1L; 153 }; 154 } 155 } 156 157 /** 158 * Implementation of VirtualThreadSchedulerMXBean when virtual threads are backed 159 * by platform threads. 160 */ 161 private static final class BoundVirtualThreadSchedulerImpl 162 extends BaseVirtualThreadSchedulerImpl { 163 @Override 164 public int getParallelism() { 165 return Integer.MAX_VALUE; 166 } 167 168 @Override 169 public void setParallelism(int size) { 170 throw new UnsupportedOperationException(); 171 } 172 173 @Override 174 public int getPoolSize() { 175 return -1; 176 } 177 178 @Override 179 public int getMountedVirtualThreadCount() { 180 return -1; 181 } 182 183 @Override 184 public long getQueuedVirtualThreadCount() { 185 return -1L; 186 } 187 } 188 189 /** 190 * Implementation of VirtualThreadSchedulerMXBean when using a custom virtual 191 * thread scheduler that does not implement VirtualThreadSchedulerMXBean. 192 */ 193 private static final class CustomVirtualThreadSchedulerImpl 194 extends BaseVirtualThreadSchedulerImpl { 195 196 @Override 197 public int getParallelism() { 198 return 1; 199 } 200 201 @Override 202 public void setParallelism(int size) { 203 throw new UnsupportedOperationException(); 204 } 205 206 @Override 207 public int getPoolSize() { 208 return -1; 209 } 210 211 @Override 212 public int getMountedVirtualThreadCount() { 213 return -1; 214 } 215 216 @Override 217 public long getQueuedVirtualThreadCount() { 218 return -1L; 219 } 220 } 221 } 222 --- EOF ---