2525package com .oracle .svm .core .jdk .management ;
2626
2727import java .lang .management .ManagementFactory ;
28+ import java .lang .management .OperatingSystemMXBean ;
2829import java .lang .management .PlatformManagedObject ;
2930import java .util .ArrayList ;
3031import java .util .Collections ;
3334import java .util .List ;
3435import java .util .Map ;
3536import java .util .Set ;
37+ import java .util .function .Supplier ;
3638
3739import javax .management .DynamicMBean ;
3840import javax .management .JMException ;
4951import org .graalvm .nativeimage .Platform ;
5052import org .graalvm .nativeimage .Platforms ;
5153
54+ import com .oracle .svm .core .SubstrateUtil ;
5255import com .oracle .svm .core .annotate .Uninterruptible ;
5356import com .oracle .svm .core .thread .ThreadListener ;
5457import com .oracle .svm .core .util .UserError ;
58+ import com .oracle .svm .core .util .VMError ;
5559import com .sun .jmx .mbeanserver .MXBeanLookup ;
5660
5761/**
6064 * parts: The beans (implementations of {@link PlatformManagedObject}) themselves; and the singleton
6165 * {@link ManagementFactory#getPlatformMBeanServer() MBean server}.
6266 *
63- * Support for {@link PlatformManagedObject}: All MXBean that provide VM introspection are allocated
64- * eagerly at image build time, and stored in {@link #platformManagedObjectsMap} as well as
65- * {@link #platformManagedObjectsSet}. The registration is decentralized: while some general beans
66- * are registered in this class, the OS specific and GC specific beans are registered in the
67- * respective OS or GC code. To find all registrations, look for the usages of
68- * {@link #addPlatformManagedObjectSingleton} and {@link #addPlatformManagedObjectList}. Eager
69- * allocation of all the beans avoids the complicated registry that the JDK maintains for lazy
70- * loading (the code in PlatformComponent - note that this code and even the package of the class is
71- * significantly different between JDK 8 and JDK 11).
67+ * Support for {@link PlatformManagedObject}: All MXBean that provide VM introspection are
68+ * registered (but not necessarily allocated) eagerly at image build time, and stored in
69+ * {@link #platformManagedObjectsMap} as well as {@link #platformManagedObjectsSet}. The
70+ * registration is decentralized: while some general beans are registered in this class, the GC
71+ * specific beans are registered in the respective GC code. To find all registrations, look for the
72+ * usages of {@link #addPlatformManagedObjectSingleton} and {@link #addPlatformManagedObjectList}.
73+ * Eager registration of all the beans avoids the complicated registry that the JDK maintains for
74+ * lazy loading (the code in PlatformComponent).
7275 *
7376 * Support for {@link ManagementFactory#getPlatformMBeanServer()}: The {@link MBeanServer} that
7477 * makes all MXBean available too is allocated lazily at run time. This has advantages and
@@ -113,6 +116,9 @@ public final class ManagementSupport implements ThreadListener {
113116 private final SubstrateRuntimeMXBean runtimeMXBean ;
114117 private final SubstrateThreadMXBean threadMXBean ;
115118
119+ /* Initialized lazily at run time. */
120+ private OperatingSystemMXBean osMXBean ;
121+
116122 /** The singleton MBean server for the platform, initialized lazily at run time. */
117123 MBeanServer platformMBeanServer ;
118124
@@ -128,7 +134,7 @@ public final class ManagementSupport implements ThreadListener {
128134
129135 /*
130136 * Register the platform objects defined in this package. Note that more platform objects
131- * are registered in OS and GC specific code.
137+ * are registered in GC specific code.
132138 */
133139 addPlatformManagedObjectSingleton (java .lang .management .ClassLoadingMXBean .class , classLoadingMXBean );
134140 addPlatformManagedObjectSingleton (java .lang .management .CompilationMXBean .class , compilationMXBean );
@@ -140,6 +146,21 @@ public final class ManagementSupport implements ThreadListener {
140146 */
141147 addPlatformManagedObjectList (java .lang .management .MemoryPoolMXBean .class , Collections .emptyList ());
142148 addPlatformManagedObjectList (java .lang .management .BufferPoolMXBean .class , Collections .emptyList ());
149+ /*
150+ * Register the platform object for the OS using a supplier that lazily initializes it at
151+ * run time.
152+ */
153+ Class <?> osMXBeanInterface = Platform .includedIn (Platform .WINDOWS .class )
154+ ? com .sun .management .OperatingSystemMXBean .class
155+ : com .sun .management .UnixOperatingSystemMXBean .class ;
156+ doAddPlatformManagedObjectSingleton (osMXBeanInterface , (PlatformManagedObjectSupplier ) this ::getOperatingSystemMXBean );
157+ }
158+
159+ private synchronized OperatingSystemMXBean getOperatingSystemMXBean () {
160+ if (osMXBean == null ) {
161+ osMXBean = SubstrateUtil .cast (new Target_com_sun_management_internal_OperatingSystemImpl (null ), OperatingSystemMXBean .class );
162+ }
163+ return osMXBean ;
143164 }
144165
145166 @ Fold
@@ -251,7 +272,7 @@ synchronized MBeanServer getPlatformMBeanServer() {
251272 /* Modified version of JDK 11: ManagementFactory.getPlatformMBeanServer */
252273 platformMBeanServer = MBeanServerFactory .createMBeanServer ();
253274 for (PlatformManagedObject platformManagedObject : platformManagedObjectsSet ) {
254- addMXBean (platformMBeanServer , platformManagedObject );
275+ addMXBean (platformMBeanServer , handleLazyPlatformManagedObjectSingleton ( platformManagedObject ) );
255276 }
256277 }
257278 return platformMBeanServer ;
@@ -287,7 +308,7 @@ <T extends PlatformManagedObject> T getPlatformMXBean(Class<T> mxbeanInterface)
287308 } else if (result instanceof List ) {
288309 throw new IllegalArgumentException (mxbeanInterface .getName () + " can have more than one instance" );
289310 }
290- return mxbeanInterface .cast (result );
311+ return mxbeanInterface .cast (handleLazyPlatformManagedObjectSingleton ( result ) );
291312 }
292313
293314 @ SuppressWarnings ("unchecked" )
@@ -299,7 +320,33 @@ <T extends PlatformManagedObject> List<T> getPlatformMXBeans(Class<T> mxbeanInte
299320 if (result instanceof List ) {
300321 return (List <T >) result ;
301322 } else {
302- return Collections .singletonList (mxbeanInterface .cast (result ));
323+ return Collections .singletonList (mxbeanInterface .cast (handleLazyPlatformManagedObjectSingleton ( result ) ));
303324 }
304325 }
326+
327+ /**
328+ * A {@link PlatformManagedObject} supplier that is itself a {@link PlatformManagedObject} for
329+ * easier integration with the rest of the {@link ManagementSupport} machinery.
330+ *
331+ * This in particular allows for transparent storage in {@link #platformManagedObjectsMap} and
332+ * {@link #platformManagedObjectsSet} at the expense of
333+ * {@linkplain #handleLazyPlatformManagedObjectSingleton special handling} when retrieving
334+ * stored platform objects.
335+ */
336+ private interface PlatformManagedObjectSupplier extends Supplier <PlatformManagedObject >, PlatformManagedObject {
337+ @ Override
338+ default ObjectName getObjectName () {
339+ throw VMError .shouldNotReachHere ();
340+ }
341+ }
342+
343+ /**
344+ * Provides {@link PlatformManagedObjectSupplier} handling when retrieving singleton platform
345+ * objects from {@link #platformManagedObjectsMap} and {@link #platformManagedObjectsSet}.
346+ */
347+ private static PlatformManagedObject handleLazyPlatformManagedObjectSingleton (Object object ) {
348+ assert object instanceof PlatformManagedObject ;
349+ return object instanceof PlatformManagedObjectSupplier ? ((PlatformManagedObjectSupplier ) object ).get ()
350+ : (PlatformManagedObject ) object ;
351+ }
305352}
0 commit comments