28
28
import java .io .File ;
29
29
import java .io .FileInputStream ;
30
30
import java .io .FileOutputStream ;
31
+ import java .io .IOException ;
31
32
import java .io .InputStream ;
32
33
import java .io .OutputStream ;
33
34
import java .lang .management .MemoryMXBean ;
34
35
import java .util .ArrayList ;
35
36
import java .util .Collections ;
36
37
import java .util .List ;
38
+ import java .util .logging .Level ;
39
+ import java .util .logging .Logger ;
40
+ import javax .management .Attribute ;
41
+ import javax .management .MBeanServerConnection ;
42
+ import javax .management .MalformedObjectNameException ;
43
+ import javax .management .ObjectName ;
37
44
import javax .swing .SwingUtilities ;
38
45
import javax .swing .event .ChangeEvent ;
39
46
import javax .swing .event .ChangeListener ;
62
69
*/
63
70
final class ApplicationMonitorModel {
64
71
72
+ private static final Logger LOGGER = Logger .getLogger (ApplicationMonitorModel .class .getName ());
65
73
private static final String PROP_PREFIX = "ApplicationMonitorModel_" ; // NOI18N
66
74
67
75
static final String SNAPSHOT_VERSION = PROP_PREFIX + "version" ; // NOI18N
@@ -82,6 +90,7 @@ final class ApplicationMonitorModel {
82
90
public static final String PROP_MEMORY_MONITORING_SUPPORTED = PROP_PREFIX + "memory_monitoring_supported" ; // NOI18N
83
91
public static final String PROP_CLASS_MONITORING_SUPPORTED = PROP_PREFIX + "class_monitoring_supported" ; // NOI18N
84
92
public static final String PROP_THREADS_MONITORING_SUPPORTED = PROP_PREFIX + "threads_monitoring_supported" ; // NOI18N
93
+ public static final String PROP_VIRTUAL_THREADS_MONITORING_SUPPORTED = PROP_PREFIX + "virtual_threads_monitoring_supported" ; // NOI18N
85
94
public static final String PROP_NUMBER_OF_PROCESSORS = PROP_PREFIX + "number_of_processors" ; // NOI18N
86
95
87
96
public static final String PROP_PROCESS_CPU_TIME = PROP_PREFIX + "process_cpu_time" ; // NOI18N
@@ -104,12 +113,17 @@ final class ApplicationMonitorModel {
104
113
public static final String PROP_DAEMON_THREADS = PROP_PREFIX + "daemon_threads" ; // NOI18N
105
114
public static final String PROP_PEAK_THREADS = PROP_PREFIX + "peak_threads" ; // NOI18N
106
115
public static final String PROP_STARTED_THREADS = PROP_PREFIX + "started_threads" ; // NOI18N
116
+ public static final String PROP_PARALLELISM = PROP_PREFIX + "parallelism" ; // NOI18N
117
+ public static final String PROP_POOL_SIZE = PROP_PREFIX + "pool_size" ; // NOI18N
118
+ public static final String PROP_MOUNTED_VIRTUAL_THREADS_COUNT = PROP_PREFIX + "mounted_virtual_thread_count" ; // NOI18N
119
+ public static final String PROP_QUEUED_VIRTUAL_THREAD_COUNT = PROP_PREFIX + "queued_virtual_thread_count" ; // NOI18N
107
120
108
121
private static final String CPU_CHART_STORAGE = "monitor_cpu.dat" ; // NOI18N
109
122
private static final String HEAP_CHART_STORAGE = "monitor_heap.dat" ; // NOI18N
110
123
private static final String PERMGEN_CHART_STORAGE = "monitor_permgen.dat" ; // NOI18N
111
124
private static final String CLASSES_CHART_STORAGE = "monitor_classes.dat" ; // NOI18N
112
125
private static final String THREADS_CHART_STORAGE = "monitor_threads.dat" ; // NOI18N
126
+ private static final String VIRTUAL_THREADS_CHART_STORAGE = "monitor_vthreads.dat" ; // NOI18N
113
127
114
128
private boolean initialized ;
115
129
private final DataSource source ;
@@ -120,6 +134,8 @@ final class ApplicationMonitorModel {
120
134
private Jvm jvm ;
121
135
private MemoryMXBean memoryMXBean ;
122
136
private MonitoredDataListener monitoredDataListener ;
137
+ private ObjectName virtualThreadsName ;
138
+ private MBeanServerConnection connection ;
123
139
124
140
private int chartCache = -1 ;
125
141
@@ -133,6 +149,7 @@ final class ApplicationMonitorModel {
133
149
private boolean memoryMonitoringSupported = false ;
134
150
private boolean classMonitoringSupported = false ;
135
151
private boolean threadsMonitoringSupported = false ;
152
+ private boolean virtualThreadsMonitoringSupported = false ;
136
153
private int processorsCount = -1 ;
137
154
138
155
private long processCpuTime = -1 ;
@@ -155,12 +172,17 @@ final class ApplicationMonitorModel {
155
172
private long daemonThreads = -1 ;
156
173
private long peakThreads = -1 ;
157
174
private long startedThreads = -1 ;
175
+ private int parallelism = -1 ;
176
+ private int poolSize = -1 ;
177
+ private int mountedVirtualThreadCount = -1 ;
178
+ private long queuedVirtualThreadCount = -1 ;
158
179
159
180
private SimpleXYChartSupport cpuChartSupport ;
160
181
private SimpleXYChartSupport heapChartSupport ;
161
182
private SimpleXYChartSupport permGenChartSupport ;
162
183
private SimpleXYChartSupport classesChartSupport ;
163
184
private SimpleXYChartSupport threadsChartSupport ;
185
+ private SimpleXYChartSupport virtualThreadsChartSupport ;
164
186
165
187
166
188
public static ApplicationMonitorModel create (Application application , boolean live ) {
@@ -186,6 +208,7 @@ public static ApplicationMonitorModel create(Snapshot snapshot) {
186
208
public boolean isMemoryMonitoringSupported () { return memoryMonitoringSupported ; }
187
209
public boolean isClassMonitoringSupported () { return classMonitoringSupported ; }
188
210
public boolean isThreadsMonitoringSupported () { return threadsMonitoringSupported ; }
211
+ public boolean isVirtualThreadsMonitoringSupported () { return virtualThreadsMonitoringSupported ; }
189
212
public int getProcessorsCount () { return processorsCount ; }
190
213
191
214
public long getTimestamp () { return timestamp ; }
@@ -212,6 +235,10 @@ public static ApplicationMonitorModel create(Snapshot snapshot) {
212
235
public long getDeamonThreads () { return daemonThreads ; }
213
236
public long getPeakThreads () { return peakThreads ; }
214
237
public long getStartedThreads () { return startedThreads ; }
238
+ public int getParallelism () { return parallelism ; }
239
+ public int getPoolSize () { return poolSize ; }
240
+ public int getMountedVirtualThreadCount () { return mountedVirtualThreadCount ; }
241
+ public long getQueuedVirtualThreadCount () { return queuedVirtualThreadCount ; }
215
242
216
243
217
244
public synchronized void initialize () {
@@ -276,6 +303,17 @@ public void run() {
276
303
});
277
304
}
278
305
306
+ public void registerVirtualThreadsChartSupport (final SimpleXYChartSupport virtualThreadsChartSupport ) {
307
+ this .virtualThreadsChartSupport = virtualThreadsChartSupport ;
308
+ if (virtualThreadsChartSupport != null && source instanceof Snapshot )
309
+ VisualVM .getInstance ().runTask (new Runnable () {
310
+ public void run () {
311
+ File file = new File (source .getStorage ().getDirectory (), VIRTUAL_THREADS_CHART_STORAGE );
312
+ if (file .isFile ()) loadChartSupport (virtualThreadsChartSupport , file );
313
+ }
314
+ });
315
+ }
316
+
279
317
public synchronized void cleanup () {
280
318
listeners .clear ();
281
319
if (!initialized ) return ;
@@ -308,6 +346,7 @@ public void save(Snapshot snapshot) {
308
346
setProperty (storage , PROP_MEMORY_MONITORING_SUPPORTED , Boolean .toString (memoryMonitoringSupported ));
309
347
setProperty (storage , PROP_CLASS_MONITORING_SUPPORTED , Boolean .toString (classMonitoringSupported ));
310
348
setProperty (storage , PROP_THREADS_MONITORING_SUPPORTED , Boolean .toString (threadsMonitoringSupported ));
349
+ setProperty (storage , PROP_VIRTUAL_THREADS_MONITORING_SUPPORTED , Boolean .toString (virtualThreadsMonitoringSupported ));
311
350
setProperty (storage , PROP_NUMBER_OF_PROCESSORS , Integer .toString (processorsCount ));
312
351
313
352
setProperty (storage , PROP_PROCESS_CPU_TIME , Long .toString (processCpuTime ));
@@ -330,6 +369,10 @@ public void save(Snapshot snapshot) {
330
369
setProperty (storage , PROP_DAEMON_THREADS , Long .toString (daemonThreads ));
331
370
setProperty (storage , PROP_PEAK_THREADS , Long .toString (peakThreads ));
332
371
setProperty (storage , PROP_STARTED_THREADS , Long .toString (startedThreads ));
372
+ setProperty (storage , PROP_PARALLELISM , Integer .toString (parallelism ));
373
+ setProperty (storage , PROP_POOL_SIZE , Integer .toString (poolSize ));
374
+ setProperty (storage , PROP_MOUNTED_VIRTUAL_THREADS_COUNT , Integer .toString (mountedVirtualThreadCount ));
375
+ setProperty (storage , PROP_QUEUED_VIRTUAL_THREAD_COUNT , Long .toString (queuedVirtualThreadCount ));
333
376
334
377
File dir = storage .getDirectory ();
335
378
@@ -343,6 +386,8 @@ public void save(Snapshot snapshot) {
343
386
saveChartSupport (classesChartSupport , new File (dir , CLASSES_CHART_STORAGE ));
344
387
if (threadsMonitoringSupported )
345
388
saveChartSupport (threadsChartSupport , new File (dir , THREADS_CHART_STORAGE ));
389
+ if (virtualThreadsMonitoringSupported )
390
+ saveChartSupport (virtualThreadsChartSupport , new File (dir , VIRTUAL_THREADS_CHART_STORAGE ));
346
391
347
392
}
348
393
@@ -378,6 +423,7 @@ private void initialize(Snapshot snapshot) {
378
423
memoryMonitoringSupported = Boolean .parseBoolean (getProperty (storage , PROP_MEMORY_MONITORING_SUPPORTED ));
379
424
classMonitoringSupported = Boolean .parseBoolean (getProperty (storage , PROP_CLASS_MONITORING_SUPPORTED ));
380
425
threadsMonitoringSupported = Boolean .parseBoolean (getProperty (storage , PROP_THREADS_MONITORING_SUPPORTED ));
426
+ virtualThreadsMonitoringSupported = Boolean .parseBoolean (getProperty (storage , PROP_VIRTUAL_THREADS_MONITORING_SUPPORTED ));
381
427
processorsCount = Integer .parseInt (getProperty (storage , PROP_NUMBER_OF_PROCESSORS ));
382
428
383
429
processCpuTime = Long .parseLong (getProperty (storage , PROP_PROCESS_CPU_TIME ));
@@ -398,6 +444,10 @@ private void initialize(Snapshot snapshot) {
398
444
daemonThreads = Long .parseLong (getProperty (storage , PROP_DAEMON_THREADS ));
399
445
peakThreads = Long .parseLong (getProperty (storage , PROP_PEAK_THREADS ));
400
446
startedThreads = Long .parseLong (getProperty (storage , PROP_STARTED_THREADS ));
447
+ parallelism = Integer .parseInt (getProperty (storage , PROP_PARALLELISM ));
448
+ poolSize = Integer .parseInt (getProperty (storage , PROP_POOL_SIZE ));
449
+ mountedVirtualThreadCount = Integer .parseInt (getProperty (storage , PROP_MOUNTED_VIRTUAL_THREADS_COUNT ));
450
+ queuedVirtualThreadCount = Long .parseLong (getProperty (storage , PROP_QUEUED_VIRTUAL_THREAD_COUNT ));
401
451
402
452
if (version .compareTo ("1.1" ) >= 0 ) { // NOI18N
403
453
heapName = getProperty (storage , PROP_HEAP_NAME );
@@ -450,6 +500,13 @@ private void initialize(Application application) {
450
500
if (mxbeans != null ) {
451
501
memoryMXBean = mxbeans .getMemoryMXBean ();
452
502
}
503
+ virtualThreadsName = getVirtualThreadsName ();
504
+ try {
505
+ virtualThreadsMonitoringSupported = jmxModel .getMBeanServerConnection ().isRegistered (virtualThreadsName );
506
+ if (virtualThreadsMonitoringSupported ) connection = jmxModel .getMBeanServerConnection ();
507
+ } catch (IOException ex ) {
508
+
509
+ }
453
510
}
454
511
455
512
if (jvm != null ) {
@@ -514,6 +571,17 @@ private void updateValues(final long time, final MonitoredData data) {
514
571
peakThreads = data .getThreadsLivePeak ();
515
572
startedThreads = data .getThreadsStarted ();
516
573
}
574
+ if (virtualThreadsMonitoringSupported ) {
575
+ Object [] attributes = getVirtualThreadAttributes ("Parallelism" , "PoolSize" , "MountedVirtualThreadCount" , "QueuedVirtualThreadCount" );
576
+ if (attributes != null ) {
577
+ parallelism = (Integer )attributes [0 ];
578
+ poolSize = (Integer )attributes [1 ];
579
+ mountedVirtualThreadCount = (Integer )attributes [2 ];
580
+ queuedVirtualThreadCount = (Long )attributes [3 ];
581
+ } else {
582
+ virtualThreadsMonitoringSupported = false ;
583
+ }
584
+ }
517
585
}
518
586
}
519
587
@@ -533,4 +601,26 @@ private ApplicationMonitorModel(DataSource source, boolean live) {
533
601
listeners = Collections .synchronizedList (new ArrayList <>());
534
602
}
535
603
604
+ private Object [] getVirtualThreadAttributes (String ... names ) {
605
+ try {
606
+ List <Attribute > attrs = connection .getAttributes (virtualThreadsName , names ).asList ();
607
+ Object [] values = new Object [attrs .size ()];
608
+
609
+ for (int i = 0 ; i < values .length ; i ++) {
610
+ values [i ] = attrs .get (i ).getValue ();
611
+ }
612
+ return values ;
613
+ } catch (Exception ex ) {
614
+ LOGGER .log (Level .INFO , "getAttributes" , ex ); // NOI18N
615
+ }
616
+ return null ;
617
+ }
618
+
619
+ private static ObjectName getVirtualThreadsName () {
620
+ try {
621
+ return new ObjectName ("jdk.management:type=VirtualThreadScheduler" ); // NOI18N
622
+ } catch (MalformedObjectNameException ex ) {
623
+ throw new RuntimeException (ex );
624
+ }
625
+ }
536
626
}
0 commit comments