Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.management/share/classes/java/lang/management/ManagementFactory.java
41159 views
1
/*
2
* Copyright (c) 2003, 2021, 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
26
package java.lang.management;
27
import java.io.FilePermission;
28
import java.io.IOException;
29
import javax.management.DynamicMBean;
30
import javax.management.MBeanServer;
31
import javax.management.MBeanServerConnection;
32
import javax.management.MBeanServerFactory;
33
import javax.management.MBeanServerPermission;
34
import javax.management.NotificationEmitter;
35
import javax.management.ObjectName;
36
import javax.management.InstanceNotFoundException;
37
import javax.management.MalformedObjectNameException;
38
import javax.management.StandardEmitterMBean;
39
import javax.management.StandardMBean;
40
import java.security.AccessController;
41
import java.security.Permission;
42
import java.security.PrivilegedAction;
43
import java.security.PrivilegedActionException;
44
import java.security.PrivilegedExceptionAction;
45
import java.util.ArrayList;
46
import java.util.Collection;
47
import java.util.Collections;
48
import java.util.HashMap;
49
import java.util.HashSet;
50
import java.util.List;
51
import java.util.Map;
52
import java.util.Optional;
53
import java.util.ServiceLoader;
54
import java.util.Set;
55
import java.util.stream.Collectors;
56
import java.util.stream.Stream;
57
import javax.management.JMX;
58
import sun.management.Util;
59
import sun.management.spi.PlatformMBeanProvider;
60
import sun.management.spi.PlatformMBeanProvider.PlatformComponent;
61
62
/**
63
* The {@code ManagementFactory} class is a factory class for getting
64
* managed beans for the Java platform.
65
* This class consists of static methods each of which returns
66
* one or more <i>platform MXBeans</i> representing
67
* the management interface of a component of the Java virtual
68
* machine.
69
*
70
* <h2><a id="MXBean">Platform MXBeans</a></h2>
71
* <p>
72
* A platform MXBean is a <i>managed bean</i> that
73
* conforms to the <a href="../../../javax/management/package-summary.html">JMX</a>
74
* Instrumentation Specification and only uses a set of basic data types.
75
* A JMX management application and the {@linkplain
76
* #getPlatformMBeanServer platform MBeanServer}
77
* can interoperate without requiring classes for MXBean specific
78
* data types.
79
* The data types being transmitted between the JMX connector
80
* server and the connector client are
81
* {@linkplain javax.management.openmbean.OpenType open types}
82
* and this allows interoperation across versions.
83
* See <a href="../../../javax/management/MXBean.html#MXBean-spec">
84
* the specification of MXBeans</a> for details.
85
*
86
* <a id="MXBeanNames"></a>
87
* <p>Each platform MXBean is a {@link PlatformManagedObject}
88
* and it has a unique
89
* {@link javax.management.ObjectName ObjectName} for
90
* registration in the platform {@code MBeanServer} as returned by
91
* by the {@link PlatformManagedObject#getObjectName getObjectName}
92
* method.
93
*
94
* <p>
95
* An application can access a platform MXBean in the following ways:
96
* <h3>1. Direct access to an MXBean interface</h3>
97
* <blockquote>
98
* <ul>
99
* <li>Get an MXBean instance by calling the
100
* {@link #getPlatformMXBean(Class) getPlatformMXBean} or
101
* {@link #getPlatformMXBeans(Class) getPlatformMXBeans} method
102
* and access the MXBean locally in the running
103
* virtual machine.
104
* </li>
105
* <li>Construct an MXBean proxy instance that forwards the
106
* method calls to a given {@link MBeanServer MBeanServer} by calling
107
* the {@link #getPlatformMXBean(MBeanServerConnection, Class)} or
108
* {@link #getPlatformMXBeans(MBeanServerConnection, Class)} method.
109
* The {@link #newPlatformMXBeanProxy newPlatformMXBeanProxy} method
110
* can also be used to construct an MXBean proxy instance of
111
* a given {@code ObjectName}.
112
* A proxy is typically constructed to remotely access
113
* an MXBean of another running virtual machine.
114
* </li>
115
* </ul>
116
* <h3>2. Indirect access to an MXBean interface via MBeanServer</h3>
117
* <ul>
118
* <li>Go through the platform {@code MBeanServer} to access MXBeans
119
* locally or a specific {@code MBeanServerConnection} to access
120
* MXBeans remotely.
121
* The attributes and operations of an MXBean use only
122
* <em>JMX open types</em> which include basic data types,
123
* {@link javax.management.openmbean.CompositeData CompositeData},
124
* and {@link javax.management.openmbean.TabularData TabularData}
125
* defined in
126
* {@link javax.management.openmbean.OpenType OpenType}.
127
* The mapping is specified in
128
* the {@linkplain javax.management.MXBean MXBean} specification
129
* for details.
130
* </li>
131
* </ul>
132
* </blockquote>
133
*
134
* <p>
135
* The {@link #getPlatformManagementInterfaces getPlatformManagementInterfaces}
136
* method returns all management interfaces supported in the Java virtual machine
137
* including the standard management interfaces listed in the tables
138
* below as well as the management interfaces extended by the JDK implementation.
139
* <p>
140
* A Java virtual machine has a single instance of the following management
141
* interfaces:
142
*
143
* <table class="striped" style="margin-left:2em">
144
* <caption style="display:none">The list of Management Interfaces and their single instances</caption>
145
* <thead>
146
* <tr>
147
* <th scope="col">Management Interface</th>
148
* <th scope="col">ObjectName</th>
149
* </tr>
150
* </thead>
151
* <tbody style="text-align:left;">
152
* <tr>
153
* <th scope="row"> {@link ClassLoadingMXBean} </th>
154
* <td> {@link #CLASS_LOADING_MXBEAN_NAME
155
* java.lang:type=ClassLoading}</td>
156
* </tr>
157
* <tr>
158
* <th scope="row"> {@link MemoryMXBean} </th>
159
* <td> {@link #MEMORY_MXBEAN_NAME
160
* java.lang:type=Memory}</td>
161
* </tr>
162
* <tr>
163
* <th scope="row"> {@link ThreadMXBean} </th>
164
* <td> {@link #THREAD_MXBEAN_NAME
165
* java.lang:type=Threading}</td>
166
* </tr>
167
* <tr>
168
* <th scope="row"> {@link RuntimeMXBean} </th>
169
* <td> {@link #RUNTIME_MXBEAN_NAME
170
* java.lang:type=Runtime}</td>
171
* </tr>
172
* <tr>
173
* <th scope="row"> {@link OperatingSystemMXBean} </th>
174
* <td> {@link #OPERATING_SYSTEM_MXBEAN_NAME
175
* java.lang:type=OperatingSystem}</td>
176
* </tr>
177
* <tr>
178
* <th scope="row"> {@link PlatformLoggingMXBean} </th>
179
* <td> {@link java.util.logging.LogManager#LOGGING_MXBEAN_NAME
180
* java.util.logging:type=Logging}</td>
181
* </tr>
182
* </tbody>
183
* </table>
184
*
185
* <p>
186
* A Java virtual machine has zero or a single instance of
187
* the following management interfaces.
188
*
189
* <table class="striped" style="margin-left:2em">
190
* <caption style="display:none">The list of Management Interfaces and their single instances</caption>
191
* <thead>
192
* <tr>
193
* <th scope="col">Management Interface</th>
194
* <th scope="col">ObjectName</th>
195
* </tr>
196
* </thead>
197
* <tbody style="text-align:left;">
198
* <tr>
199
* <th scope="row"> {@link CompilationMXBean} </th>
200
* <td> {@link #COMPILATION_MXBEAN_NAME
201
* java.lang:type=Compilation}</td>
202
* </tr>
203
* </tbody>
204
* </table>
205
*
206
* <p>
207
* A Java virtual machine may have one or more instances of the following
208
* management interfaces.
209
* <table class="striped" style="margin-left:2em">
210
* <caption style="display:none">The list of Management Interfaces and their single instances</caption>
211
* <thead>
212
* <tr>
213
* <th scope="col">Management Interface</th>
214
* <th scope="col">ObjectName</th>
215
* </tr>
216
* </thead>
217
* <tbody style="text-align:left;">
218
* <tr>
219
* <th scope="row"> {@link GarbageCollectorMXBean} </th>
220
* <td> {@link #GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE
221
* java.lang:type=GarbageCollector}{@code ,name=}<i>collector's name</i></td>
222
* </tr>
223
* <tr>
224
* <th scope="row"> {@link MemoryManagerMXBean} </th>
225
* <td> {@link #MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE
226
* java.lang:type=MemoryManager}{@code ,name=}<i>manager's name</i></td>
227
* </tr>
228
* <tr>
229
* <th scope="row"> {@link MemoryPoolMXBean} </th>
230
* <td> {@link #MEMORY_POOL_MXBEAN_DOMAIN_TYPE
231
* java.lang:type=MemoryPool}{@code ,name=}<i>pool's name</i></td>
232
* </tr>
233
* <tr>
234
* <th scope="row"> {@link BufferPoolMXBean} </th>
235
* <td> {@code java.nio:type=BufferPool,name=}<i>pool name</i></td>
236
* </tr>
237
* </tbody>
238
* </table>
239
*
240
* @see <a href="../../../javax/management/package-summary.html">
241
* JMX Specification</a>
242
* @see <a href="package-summary.html#examples">
243
* Ways to Access Management Metrics</a>
244
* @see javax.management.MXBean
245
*
246
* @author Mandy Chung
247
* @since 1.5
248
*/
249
@SuppressWarnings("removal")
250
public class ManagementFactory {
251
// A class with only static fields and methods.
252
private ManagementFactory() {};
253
254
/**
255
* String representation of the
256
* {@code ObjectName} for the {@link ClassLoadingMXBean}.
257
*/
258
public static final String CLASS_LOADING_MXBEAN_NAME =
259
"java.lang:type=ClassLoading";
260
261
/**
262
* String representation of the
263
* {@code ObjectName} for the {@link CompilationMXBean}.
264
*/
265
public static final String COMPILATION_MXBEAN_NAME =
266
"java.lang:type=Compilation";
267
268
/**
269
* String representation of the
270
* {@code ObjectName} for the {@link MemoryMXBean}.
271
*/
272
public static final String MEMORY_MXBEAN_NAME =
273
"java.lang:type=Memory";
274
275
/**
276
* String representation of the
277
* {@code ObjectName} for the {@link OperatingSystemMXBean}.
278
*/
279
public static final String OPERATING_SYSTEM_MXBEAN_NAME =
280
"java.lang:type=OperatingSystem";
281
282
/**
283
* String representation of the
284
* {@code ObjectName} for the {@link RuntimeMXBean}.
285
*/
286
public static final String RUNTIME_MXBEAN_NAME =
287
"java.lang:type=Runtime";
288
289
/**
290
* String representation of the
291
* {@code ObjectName} for the {@link ThreadMXBean}.
292
*/
293
public static final String THREAD_MXBEAN_NAME =
294
"java.lang:type=Threading";
295
296
/**
297
* The domain name and the type key property in
298
* the {@code ObjectName} for a {@link GarbageCollectorMXBean}.
299
* The unique {@code ObjectName} for a {@code GarbageCollectorMXBean}
300
* can be formed by appending this string with
301
* "{@code ,name=}<i>collector's name</i>".
302
*/
303
public static final String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE =
304
"java.lang:type=GarbageCollector";
305
306
/**
307
* The domain name and the type key property in
308
* the {@code ObjectName} for a {@link MemoryManagerMXBean}.
309
* The unique {@code ObjectName} for a {@code MemoryManagerMXBean}
310
* can be formed by appending this string with
311
* "{@code ,name=}<i>manager's name</i>".
312
*/
313
public static final String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE=
314
"java.lang:type=MemoryManager";
315
316
/**
317
* The domain name and the type key property in
318
* the {@code ObjectName} for a {@link MemoryPoolMXBean}.
319
* The unique {@code ObjectName} for a {@code MemoryPoolMXBean}
320
* can be formed by appending this string with
321
* {@code ,name=}<i>pool's name</i>.
322
*/
323
public static final String MEMORY_POOL_MXBEAN_DOMAIN_TYPE=
324
"java.lang:type=MemoryPool";
325
326
/**
327
* Returns the managed bean for the class loading system of
328
* the Java virtual machine.
329
*
330
* @return a {@link ClassLoadingMXBean} object for
331
* the Java virtual machine.
332
*/
333
public static ClassLoadingMXBean getClassLoadingMXBean() {
334
return getPlatformMXBean(ClassLoadingMXBean.class);
335
}
336
337
/**
338
* Returns the managed bean for the memory system of
339
* the Java virtual machine.
340
*
341
* @return a {@link MemoryMXBean} object for the Java virtual machine.
342
*/
343
public static MemoryMXBean getMemoryMXBean() {
344
return getPlatformMXBean(MemoryMXBean.class);
345
}
346
347
/**
348
* Returns the managed bean for the thread system of
349
* the Java virtual machine.
350
*
351
* @return a {@link ThreadMXBean} object for the Java virtual machine.
352
*/
353
public static ThreadMXBean getThreadMXBean() {
354
return getPlatformMXBean(ThreadMXBean.class);
355
}
356
357
/**
358
* Returns the managed bean for the runtime system of
359
* the Java virtual machine.
360
*
361
* @return a {@link RuntimeMXBean} object for the Java virtual machine.
362
363
*/
364
public static RuntimeMXBean getRuntimeMXBean() {
365
return getPlatformMXBean(RuntimeMXBean.class);
366
}
367
368
/**
369
* Returns the managed bean for the compilation system of
370
* the Java virtual machine. This method returns {@code null}
371
* if the Java virtual machine has no compilation system.
372
*
373
* @return a {@link CompilationMXBean} object for the Java virtual
374
* machine or {@code null} if the Java virtual machine has
375
* no compilation system.
376
*/
377
public static CompilationMXBean getCompilationMXBean() {
378
return getPlatformMXBean(CompilationMXBean.class);
379
}
380
381
/**
382
* Returns the managed bean for the operating system on which
383
* the Java virtual machine is running.
384
*
385
* @return an {@link OperatingSystemMXBean} object for
386
* the Java virtual machine.
387
*/
388
public static OperatingSystemMXBean getOperatingSystemMXBean() {
389
return getPlatformMXBean(OperatingSystemMXBean.class);
390
}
391
392
/**
393
* Returns a list of {@link MemoryPoolMXBean} objects in the
394
* Java virtual machine.
395
* The Java virtual machine can have one or more memory pools.
396
* It may add or remove memory pools during execution.
397
*
398
* @return a list of {@code MemoryPoolMXBean} objects.
399
*
400
*/
401
public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
402
return getPlatformMXBeans(MemoryPoolMXBean.class);
403
}
404
405
/**
406
* Returns a list of {@link MemoryManagerMXBean} objects
407
* in the Java virtual machine.
408
* The Java virtual machine can have one or more memory managers.
409
* It may add or remove memory managers during execution.
410
*
411
* @return a list of {@code MemoryManagerMXBean} objects.
412
*
413
*/
414
public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() {
415
return getPlatformMXBeans(MemoryManagerMXBean.class);
416
}
417
418
419
/**
420
* Returns a list of {@link GarbageCollectorMXBean} objects
421
* in the Java virtual machine.
422
* The Java virtual machine may have one or more
423
* {@code GarbageCollectorMXBean} objects.
424
* It may add or remove {@code GarbageCollectorMXBean}
425
* during execution.
426
*
427
* @return a list of {@code GarbageCollectorMXBean} objects.
428
*
429
*/
430
public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
431
return getPlatformMXBeans(GarbageCollectorMXBean.class);
432
}
433
434
private static MBeanServer platformMBeanServer;
435
/**
436
* Returns the platform {@link javax.management.MBeanServer MBeanServer}.
437
* On the first call to this method, it first creates the platform
438
* {@code MBeanServer} by calling the
439
* {@link javax.management.MBeanServerFactory#createMBeanServer
440
* MBeanServerFactory.createMBeanServer}
441
* method and registers each platform MXBean in this platform
442
* {@code MBeanServer} with its
443
* {@link PlatformManagedObject#getObjectName ObjectName}.
444
* This method, in subsequent calls, will simply return the
445
* initially created platform {@code MBeanServer}.
446
* <p>
447
* MXBeans that get created and destroyed dynamically, for example,
448
* memory {@link MemoryPoolMXBean pools} and
449
* {@link MemoryManagerMXBean managers},
450
* will automatically be registered and deregistered into the platform
451
* {@code MBeanServer}.
452
* <p>
453
* If the system property {@code javax.management.builder.initial}
454
* is set, the platform {@code MBeanServer} creation will be done
455
* by the specified {@link javax.management.MBeanServerBuilder}.
456
* <p>
457
* It is recommended that this platform MBeanServer also be used
458
* to register other application managed beans
459
* besides the platform MXBeans.
460
* This will allow all MBeans to be published through the same
461
* {@code MBeanServer} and hence allow for easier network publishing
462
* and discovery.
463
* Name conflicts with the platform MXBeans should be avoided.
464
*
465
* @return the platform {@code MBeanServer}; the platform
466
* MXBeans are registered into the platform {@code MBeanServer}
467
* at the first time this method is called.
468
*
469
* @throws SecurityException if there is a security manager
470
* and the caller does not have the permission required by
471
* {@link javax.management.MBeanServerFactory#createMBeanServer}.
472
*
473
* @see javax.management.MBeanServerFactory
474
* @see javax.management.MBeanServerFactory#createMBeanServer
475
*/
476
public static synchronized MBeanServer getPlatformMBeanServer() {
477
SecurityManager sm = System.getSecurityManager();
478
if (sm != null) {
479
Permission perm = new MBeanServerPermission("createMBeanServer");
480
sm.checkPermission(perm);
481
}
482
483
if (platformMBeanServer == null) {
484
platformMBeanServer = MBeanServerFactory.createMBeanServer();
485
platformComponents()
486
.stream()
487
.filter(PlatformComponent::shouldRegister)
488
.flatMap(pc -> pc.nameToMBeanMap().entrySet().stream())
489
.forEach(entry -> addMXBean(platformMBeanServer, entry.getKey(), entry.getValue()));
490
}
491
return platformMBeanServer;
492
}
493
494
/**
495
* Returns a proxy for a platform MXBean interface of a
496
* given <a href="#MXBeanNames">MXBean name</a>
497
* that forwards its method calls through the given
498
* {@code MBeanServerConnection}.
499
*
500
* <p>This method is equivalent to:
501
* <blockquote>
502
* {@link java.lang.reflect.Proxy#newProxyInstance
503
* Proxy.newProxyInstance}{@code (mxbeanInterface.getClassLoader(),
504
* new Class[] { mxbeanInterface }, handler)}
505
* </blockquote>
506
*
507
* where {@code handler} is an {@link java.lang.reflect.InvocationHandler
508
* InvocationHandler} to which method invocations to the MXBean interface
509
* are dispatched. This {@code handler} converts an input parameter
510
* from an MXBean data type to its mapped open type before forwarding
511
* to the {@code MBeanServer} and converts a return value from
512
* an MXBean method call through the {@code MBeanServer}
513
* from an open type to the corresponding return type declared in
514
* the MXBean interface.
515
*
516
* <p>
517
* If the MXBean is a notification emitter (i.e.,
518
* it implements
519
* {@link javax.management.NotificationEmitter NotificationEmitter}),
520
* both the {@code mxbeanInterface} and {@code NotificationEmitter}
521
* will be implemented by this proxy.
522
*
523
* <p>
524
* <b>Notes:</b>
525
* <ol>
526
* <li>Using an MXBean proxy is a convenience remote access to
527
* a platform MXBean of a running virtual machine. All method
528
* calls to the MXBean proxy are forwarded to an
529
* {@code MBeanServerConnection} where
530
* {@link java.io.IOException IOException} may be thrown
531
* when the communication problem occurs with the connector server.
532
* If thrown, {@link java.io.IOException IOException} will be wrappped in
533
* {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}.
534
* An application remotely accessing the platform MXBeans using
535
* proxy should prepare to catch {@code UndeclaredThrowableException} and
536
* handle its {@linkplain java.lang.reflect.UndeclaredThrowableException#getCause() cause}
537
* as if that cause had been thrown by the {@code MBeanServerConnection}
538
* interface.</li>
539
*
540
* <li>When a client application is designed to remotely access MXBeans
541
* for a running virtual machine whose version is different than
542
* the version on which the application is running,
543
* it should prepare to catch
544
* {@link java.io.InvalidObjectException InvalidObjectException}
545
* which is thrown when an MXBean proxy receives a name of an
546
* enum constant which is missing in the enum class loaded in
547
* the client application. If thrown,
548
* {@link java.io.InvalidObjectException InvalidObjectException} will be
549
* wrappped in
550
* {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}.
551
* </li>
552
*
553
* <li>{@link javax.management.MBeanServerInvocationHandler
554
* MBeanServerInvocationHandler} or its
555
* {@link javax.management.MBeanServerInvocationHandler#newProxyInstance
556
* newProxyInstance} method cannot be used to create
557
* a proxy for a platform MXBean. The proxy object created
558
* by {@code MBeanServerInvocationHandler} does not handle
559
* the properties of the platform MXBeans described in
560
* the <a href="#MXBean">class specification</a>.
561
*</li>
562
* </ol>
563
*
564
* @param connection the {@code MBeanServerConnection} to forward to.
565
* @param mxbeanName the name of a platform MXBean within
566
* {@code connection} to forward to. {@code mxbeanName} must be
567
* in the format of {@link ObjectName ObjectName}.
568
* @param mxbeanInterface the MXBean interface to be implemented
569
* by the proxy.
570
* @param <T> an {@code mxbeanInterface} type parameter
571
*
572
* @return a proxy for a platform MXBean interface of a
573
* given <a href="#MXBeanNames">MXBean name</a>
574
* that forwards its method calls through the given
575
* {@code MBeanServerConnection}, or {@code null} if not exist.
576
*
577
* @throws IllegalArgumentException if
578
* <ul>
579
* <li>{@code mxbeanName} is not with a valid
580
* {@link ObjectName ObjectName} format, or</li>
581
* <li>the named MXBean in the {@code connection} is
582
* not a MXBean provided by the platform, or</li>
583
* <li>the named MXBean is not registered in the
584
* {@code MBeanServerConnection}, or</li>
585
* <li>the named MXBean is not an instance of the given
586
* {@code mxbeanInterface}</li>
587
* </ul>
588
*
589
* @throws java.io.IOException if a communication problem
590
* occurred when accessing the {@code MBeanServerConnection}.
591
*/
592
public static <T> T
593
newPlatformMXBeanProxy(MBeanServerConnection connection,
594
String mxbeanName,
595
Class<T> mxbeanInterface)
596
throws java.io.IOException {
597
598
// Only allow MXBean interfaces from the platform modules loaded by the
599
// bootstrap or platform class loader
600
final Class<?> cls = mxbeanInterface;
601
ClassLoader loader =
602
AccessController.doPrivileged(
603
(PrivilegedAction<ClassLoader>) () -> cls.getClassLoader());
604
if (!jdk.internal.misc.VM.isSystemDomainLoader(loader)) {
605
throw new IllegalArgumentException(mxbeanName +
606
" is not a platform MXBean");
607
}
608
609
try {
610
final ObjectName objName = new ObjectName(mxbeanName);
611
String intfName = mxbeanInterface.getName();
612
if (!isInstanceOf(connection, objName, intfName)) {
613
throw new IllegalArgumentException(mxbeanName +
614
" is not an instance of " + mxbeanInterface);
615
}
616
617
// check if the registered MBean is a notification emitter
618
boolean emitter = connection.isInstanceOf(objName, NOTIF_EMITTER);
619
620
// create an MXBean proxy
621
return JMX.newMXBeanProxy(connection, objName, mxbeanInterface,
622
emitter);
623
} catch (InstanceNotFoundException|MalformedObjectNameException e) {
624
throw new IllegalArgumentException(e);
625
}
626
}
627
628
// This makes it possible to obtain an instance of LoggingMXBean
629
// using newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class)
630
// even though the underlying MXBean no longer implements
631
// java.util.logging.LoggingMXBean.
632
// Altough java.util.logging.LoggingMXBean is deprecated, an application
633
// that uses newPlatformMXBeanProxy(mbs, on, LoggingMXBean.class) will
634
// continue to work.
635
//
636
private static boolean isInstanceOf(MBeanServerConnection connection,
637
ObjectName objName, String intfName)
638
throws InstanceNotFoundException, IOException
639
{
640
// special case for java.util.logging.LoggingMXBean.
641
// java.util.logging.LoggingMXBean is deprecated and
642
// replaced with java.lang.management.PlatformLoggingMXBean,
643
// so we will consider that any MBean implementing
644
// java.lang.management.PlatformLoggingMXBean also implements
645
// java.util.logging.LoggingMXBean.
646
if ("java.util.logging.LoggingMXBean".equals(intfName)) {
647
if (connection.isInstanceOf(objName,
648
PlatformLoggingMXBean.class.getName())) {
649
return true;
650
}
651
}
652
return connection.isInstanceOf(objName, intfName);
653
}
654
655
/**
656
* Returns the platform MXBean implementing
657
* the given {@code mxbeanInterface} which is specified
658
* to have one single instance in the Java virtual machine.
659
* This method may return {@code null} if the management interface
660
* is not implemented in the Java virtual machine (for example,
661
* a Java virtual machine with no compilation system does not
662
* implement {@link CompilationMXBean});
663
* otherwise, this method is equivalent to calling:
664
* <pre>
665
* {@link #getPlatformMXBeans(Class)
666
* getPlatformMXBeans(mxbeanInterface)}.get(0);
667
* </pre>
668
*
669
* @param mxbeanInterface a management interface for a platform
670
* MXBean with one single instance in the Java virtual machine
671
* if implemented.
672
* @param <T> an {@code mxbeanInterface} type parameter
673
*
674
* @return the platform MXBean that implements
675
* {@code mxbeanInterface}, or {@code null} if not exist.
676
*
677
* @throws IllegalArgumentException if {@code mxbeanInterface}
678
* is not a platform management interface or
679
* not a singleton platform MXBean.
680
*
681
* @since 1.7
682
*/
683
public static <T extends PlatformManagedObject>
684
T getPlatformMXBean(Class<T> mxbeanInterface) {
685
PlatformComponent<?> pc = PlatformMBeanFinder.findSingleton(mxbeanInterface);
686
687
List<? extends T> mbeans = pc.getMBeans(mxbeanInterface);
688
assert mbeans.isEmpty() || mbeans.size() == 1;
689
return mbeans.isEmpty() ? null : mbeans.get(0);
690
}
691
692
/**
693
* Returns the list of platform MXBeans implementing
694
* the given {@code mxbeanInterface} in the Java
695
* virtual machine.
696
* The returned list may contain zero, one, or more instances.
697
* The number of instances in the returned list is defined
698
* in the specification of the given management interface.
699
* The order is undefined and there is no guarantee that
700
* the list returned is in the same order as previous invocations.
701
*
702
* @param mxbeanInterface a management interface for a platform
703
* MXBean
704
* @param <T> an {@code mxbeanInterface} type parameter
705
*
706
* @return the list of platform MXBeans that implement
707
* {@code mxbeanInterface}.
708
*
709
* @throws IllegalArgumentException if {@code mxbeanInterface}
710
* is not a platform management interface.
711
*
712
* @since 1.7
713
*/
714
public static <T extends PlatformManagedObject> List<T>
715
getPlatformMXBeans(Class<T> mxbeanInterface) {
716
// Validates at first the specified interface by finding at least one
717
// PlatformComponent whose MXBean implements this interface.
718
// An interface can be implemented by different MBeans, provided by
719
// different platform components.
720
PlatformComponent<?> pc = PlatformMBeanFinder.findFirst(mxbeanInterface);
721
if (pc == null) {
722
throw new IllegalArgumentException(mxbeanInterface.getName()
723
+ " is not a platform management interface");
724
}
725
726
return platformComponents().stream()
727
.flatMap(p -> p.getMBeans(mxbeanInterface).stream())
728
.collect(Collectors.toList());
729
}
730
731
/**
732
* Returns the platform MXBean proxy for
733
* {@code mxbeanInterface} which is specified to have one single
734
* instance in a Java virtual machine and the proxy will
735
* forward the method calls through the given {@code MBeanServerConnection}.
736
* This method may return {@code null} if the management interface
737
* is not implemented in the Java virtual machine being monitored
738
* (for example, a Java virtual machine with no compilation system
739
* does not implement {@link CompilationMXBean});
740
* otherwise, this method is equivalent to calling:
741
* <pre>
742
* {@link #getPlatformMXBeans(MBeanServerConnection, Class)
743
* getPlatformMXBeans(connection, mxbeanInterface)}.get(0);
744
* </pre>
745
*
746
* @param connection the {@code MBeanServerConnection} to forward to.
747
* @param mxbeanInterface a management interface for a platform
748
* MXBean with one single instance in the Java virtual machine
749
* being monitored, if implemented.
750
* @param <T> an {@code mxbeanInterface} type parameter
751
*
752
* @return the platform MXBean proxy for
753
* forwarding the method calls of the {@code mxbeanInterface}
754
* through the given {@code MBeanServerConnection},
755
* or {@code null} if not exist.
756
*
757
* @throws IllegalArgumentException if {@code mxbeanInterface}
758
* is not a platform management interface or
759
* not a singleton platform MXBean.
760
* @throws java.io.IOException if a communication problem
761
* occurred when accessing the {@code MBeanServerConnection}.
762
*
763
* @see #newPlatformMXBeanProxy
764
* @since 1.7
765
*/
766
public static <T extends PlatformManagedObject>
767
T getPlatformMXBean(MBeanServerConnection connection,
768
Class<T> mxbeanInterface)
769
throws java.io.IOException
770
{
771
PlatformComponent<?> pc = PlatformMBeanFinder.findSingleton(mxbeanInterface);
772
return newPlatformMXBeanProxy(connection, pc.getObjectNamePattern(), mxbeanInterface);
773
}
774
775
/**
776
* Returns the list of the platform MXBean proxies for
777
* forwarding the method calls of the {@code mxbeanInterface}
778
* through the given {@code MBeanServerConnection}.
779
* The returned list may contain zero, one, or more instances.
780
* The number of instances in the returned list is defined
781
* in the specification of the given management interface.
782
* The order is undefined and there is no guarantee that
783
* the list returned is in the same order as previous invocations.
784
*
785
* @param connection the {@code MBeanServerConnection} to forward to.
786
* @param mxbeanInterface a management interface for a platform
787
* MXBean
788
* @param <T> an {@code mxbeanInterface} type parameter
789
*
790
* @return the list of platform MXBean proxies for
791
* forwarding the method calls of the {@code mxbeanInterface}
792
* through the given {@code MBeanServerConnection}.
793
*
794
* @throws IllegalArgumentException if {@code mxbeanInterface}
795
* is not a platform management interface.
796
*
797
* @throws java.io.IOException if a communication problem
798
* occurred when accessing the {@code MBeanServerConnection}.
799
*
800
* @see #newPlatformMXBeanProxy
801
* @since 1.7
802
*/
803
public static <T extends PlatformManagedObject>
804
List<T> getPlatformMXBeans(MBeanServerConnection connection,
805
Class<T> mxbeanInterface)
806
throws java.io.IOException
807
{
808
// Validates at first the specified interface by finding at least one
809
// PlatformComponent whose MXBean implements this interface.
810
// An interface can be implemented by different MBeans, provided by
811
// different platform components.
812
PlatformComponent<?> pc = PlatformMBeanFinder.findFirst(mxbeanInterface);
813
if (pc == null) {
814
throw new IllegalArgumentException(mxbeanInterface.getName()
815
+ " is not a platform management interface");
816
}
817
818
// Collect all names, eliminate duplicates.
819
Stream<String> names = Stream.empty();
820
for (PlatformComponent<?> p : platformComponents()) {
821
names = Stream.concat(names, getProxyNames(p, connection, mxbeanInterface));
822
}
823
Set<String> objectNames = names.collect(Collectors.toSet());
824
if (objectNames.isEmpty()) return Collections.emptyList();
825
826
// Map names on proxies.
827
List<T> proxies = new ArrayList<>();
828
for (String name : objectNames) {
829
proxies.add(newPlatformMXBeanProxy(connection, name, mxbeanInterface));
830
}
831
return proxies;
832
}
833
834
// Returns a stream containing all ObjectNames of the MBeans represented by
835
// the specified PlatformComponent and implementing the specified interface.
836
// If the PlatformComponent is a singleton, the name returned by
837
// PlatformComponent.getObjectNamePattern() will be used, otherwise
838
// we will query the specified MBeanServerConnection (conn.queryNames)
839
// with the pattern returned by PlatformComponent.getObjectNamePattern()
840
// in order to find the names of matching MBeans.
841
// In case of singleton, we do not check whether the MBean is registered
842
// in the connection because the caller "getPlatformMXBeans" will do the check
843
// when creating a proxy.
844
private static Stream<String> getProxyNames(PlatformComponent<?> pc,
845
MBeanServerConnection conn,
846
Class<?> intf)
847
throws IOException
848
{
849
if (pc.mbeanInterfaceNames().contains(intf.getName())) {
850
if (pc.isSingleton()) {
851
return Stream.of(pc.getObjectNamePattern());
852
} else {
853
return conn.queryNames(Util.newObjectName(pc.getObjectNamePattern()), null)
854
.stream().map(ObjectName::getCanonicalName);
855
}
856
}
857
return Stream.empty();
858
}
859
860
/**
861
* Returns the set of {@code Class} objects, subinterface of
862
* {@link PlatformManagedObject}, representing
863
* all management interfaces for
864
* monitoring and managing the Java platform.
865
*
866
* @return the set of {@code Class} objects, subinterface of
867
* {@link PlatformManagedObject} representing
868
* the management interfaces for
869
* monitoring and managing the Java platform.
870
*
871
* @since 1.7
872
*/
873
public static Set<Class<? extends PlatformManagedObject>>
874
getPlatformManagementInterfaces()
875
{
876
// local variable required here; see JDK-8223553
877
Stream<Class<? extends PlatformManagedObject>> pmos = platformComponents()
878
.stream()
879
.flatMap(pc -> pc.mbeanInterfaces().stream())
880
.filter(clazz -> PlatformManagedObject.class.isAssignableFrom(clazz))
881
.map(clazz -> clazz.asSubclass(PlatformManagedObject.class));
882
return pmos.collect(Collectors.toSet());
883
}
884
885
private static final String NOTIF_EMITTER =
886
"javax.management.NotificationEmitter";
887
888
private static void addMXBean(final MBeanServer mbs, String name, final Object pmo)
889
{
890
try {
891
ObjectName oname = ObjectName.getInstance(name);
892
// Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
893
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
894
final DynamicMBean dmbean;
895
if (pmo instanceof DynamicMBean) {
896
dmbean = DynamicMBean.class.cast(pmo);
897
} else if (pmo instanceof NotificationEmitter) {
898
dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
899
} else {
900
dmbean = new StandardMBean(pmo, null, true);
901
}
902
903
mbs.registerMBean(dmbean, oname);
904
return null;
905
});
906
} catch (MalformedObjectNameException mone) {
907
throw new IllegalArgumentException(mone);
908
} catch (PrivilegedActionException e) {
909
throw new RuntimeException(e.getException());
910
}
911
}
912
913
private static Collection<PlatformComponent<?>> platformComponents()
914
{
915
return PlatformMBeanFinder.getMap().values();
916
}
917
918
private static class PlatformMBeanFinder {
919
private static final Map<String, PlatformComponent<?>> componentMap;
920
921
static {
922
// get all providers
923
List<PlatformMBeanProvider> providers = AccessController.doPrivileged(
924
new PrivilegedAction<List<PlatformMBeanProvider>>() {
925
@Override
926
public List<PlatformMBeanProvider> run() {
927
List<PlatformMBeanProvider> all = new ArrayList<>();
928
for (PlatformMBeanProvider provider : ServiceLoader.loadInstalled(PlatformMBeanProvider.class)) {
929
all.add(provider);
930
}
931
all.add(new DefaultPlatformMBeanProvider());
932
return all;
933
}
934
}, null, new FilePermission("<<ALL FILES>>", "read"),
935
new RuntimePermission("sun.management.spi.PlatformMBeanProvider.subclass"));
936
937
// load all platform components into a map
938
var map = new HashMap<String, PlatformComponent<?>>();
939
for (PlatformMBeanProvider provider : providers) {
940
// For each provider, ensure that two different components are not declared
941
// with the same object name pattern.
942
var names = new HashSet<String>();
943
for (PlatformComponent<?> component : provider.getPlatformComponentList()) {
944
String name = component.getObjectNamePattern();
945
if (!names.add(name)) {
946
throw new InternalError(name +
947
" has been used as key by this provider" +
948
", it cannot be reused for " + component);
949
}
950
// The first one wins if multiple PlatformComponents defined by
951
// different providers use the same ObjectName pattern
952
map.putIfAbsent(name, component);
953
}
954
}
955
componentMap = map;
956
}
957
958
static Map<String, PlatformComponent<?>> getMap() {
959
return componentMap;
960
}
961
962
// Finds the first PlatformComponent whose mbeanInterfaceNames() list
963
// contains the specified class name. An MBean interface can be implemented
964
// by different MBeans, provided by different platform components.
965
// For instance the MemoryManagerMXBean interface is implemented both by
966
// regular memory managers, and garbage collector MXBeans. This method is
967
// mainly used to verify that there is at least one PlatformComponent
968
// which provides an implementation of the desired interface.
969
static PlatformComponent<?> findFirst(Class<?> mbeanIntf)
970
{
971
String name = mbeanIntf.getName();
972
Optional<PlatformComponent<?>> op = getMap().values()
973
.stream()
974
.filter(pc -> pc.mbeanInterfaceNames().contains(name))
975
.findFirst();
976
977
if (op.isPresent()) {
978
return op.get();
979
} else {
980
return null;
981
}
982
}
983
984
// Finds a PlatformComponent whose mbeanInterface name list contains
985
// the specified class name, and make sure that one and only one exists.
986
static PlatformComponent<?> findSingleton(Class<?> mbeanIntf)
987
{
988
String name = mbeanIntf.getName();
989
Optional<PlatformComponent<?>> op = getMap().values()
990
.stream()
991
.filter(pc -> pc.mbeanInterfaceNames().contains(name))
992
.reduce((p1, p2) -> {
993
if (p2 != null) {
994
throw new IllegalArgumentException(mbeanIntf.getName() +
995
" can have more than one instance");
996
} else {
997
return p1;
998
}
999
});
1000
1001
PlatformComponent<?> singleton = op.isPresent() ? op.get() : null;
1002
if (singleton == null) {
1003
throw new IllegalArgumentException(mbeanIntf.getName() +
1004
" is not a platform management interface");
1005
}
1006
if (!singleton.isSingleton()) {
1007
throw new IllegalArgumentException(mbeanIntf.getName() +
1008
" can have more than one instance");
1009
}
1010
return singleton;
1011
}
1012
}
1013
1014
static {
1015
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
1016
System.loadLibrary("management");
1017
return null;
1018
});
1019
}
1020
}
1021
1022