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 ;
4850import org .graalvm .nativeimage .IsolateThread ;
4951import org .graalvm .nativeimage .Platform ;
5052import org .graalvm .nativeimage .Platforms ;
53+ import org .graalvm .nativeimage .impl .InternalPlatform ;
5154
55+ import com .oracle .svm .core .SubstrateUtil ;
5256import com .oracle .svm .core .annotate .Uninterruptible ;
5357import com .oracle .svm .core .thread .ThreadListener ;
5458import com .oracle .svm .core .util .UserError ;
59+ import com .oracle .svm .core .util .VMError ;
5560import com .sun .jmx .mbeanserver .MXBeanLookup ;
5661
5762/**
6065 * parts: The beans (implementations of {@link PlatformManagedObject}) themselves; and the singleton
6166 * {@link ManagementFactory#getPlatformMBeanServer() MBean server}.
6267 *
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).
68+ * Support for {@link PlatformManagedObject}: All MXBean that provide VM introspection are
69+ * registered (but not necessarily allocated) eagerly at image build time, and stored in
70+ * {@link #platformManagedObjectsMap} as well as {@link #platformManagedObjectsSet}. The
71+ * registration is decentralized: while some general beans are registered in this class, the GC
72+ * specific beans are registered in the respective GC code. To find all registrations, look for the
73+ * usages of {@link #addPlatformManagedObjectSingleton} and {@link #addPlatformManagedObjectList}.
74+ * Eager registration of all the beans avoids the complicated registry that the JDK maintains for
75+ * lazy loading (the code in PlatformComponent).
7276 *
7377 * Support for {@link ManagementFactory#getPlatformMBeanServer()}: The {@link MBeanServer} that
7478 * makes all MXBean available too is allocated lazily at run time. This has advantages and
@@ -113,6 +117,9 @@ public final class ManagementSupport implements ThreadListener {
113117 private final SubstrateRuntimeMXBean runtimeMXBean ;
114118 private final SubstrateThreadMXBean threadMXBean ;
115119
120+ /* Initialized lazily at run time. */
121+ private OperatingSystemMXBean osMXBean ;
122+
116123 /** The singleton MBean server for the platform, initialized lazily at run time. */
117124 MBeanServer platformMBeanServer ;
118125
@@ -128,7 +135,7 @@ public final class ManagementSupport implements ThreadListener {
128135
129136 /*
130137 * Register the platform objects defined in this package. Note that more platform objects
131- * are registered in OS and GC specific code.
138+ * are registered in GC specific code.
132139 */
133140 addPlatformManagedObjectSingleton (java .lang .management .ClassLoadingMXBean .class , classLoadingMXBean );
134141 addPlatformManagedObjectSingleton (java .lang .management .CompilationMXBean .class , compilationMXBean );
@@ -140,6 +147,30 @@ public final class ManagementSupport implements ThreadListener {
140147 */
141148 addPlatformManagedObjectList (java .lang .management .MemoryPoolMXBean .class , Collections .emptyList ());
142149 addPlatformManagedObjectList (java .lang .management .BufferPoolMXBean .class , Collections .emptyList ());
150+ /*
151+ * Register the platform object for the OS using a supplier that lazily initializes it at
152+ * run time.
153+ */
154+ doAddPlatformManagedObjectSingleton (getOsMXBeanInterface (), (PlatformManagedObjectSupplier ) this ::getOsMXBean );
155+ }
156+
157+ private static Class <?> getOsMXBeanInterface () {
158+ if (Platform .includedIn (InternalPlatform .PLATFORM_JNI .class )) {
159+ return Platform .includedIn (Platform .WINDOWS .class )
160+ ? com .sun .management .OperatingSystemMXBean .class
161+ : com .sun .management .UnixOperatingSystemMXBean .class ;
162+ }
163+ return java .lang .management .OperatingSystemMXBean .class ;
164+ }
165+
166+ private synchronized OperatingSystemMXBean getOsMXBean () {
167+ if (osMXBean == null ) {
168+ Object osMXBeanImpl = Platform .includedIn (InternalPlatform .PLATFORM_JNI .class )
169+ ? new Target_com_sun_management_internal_OperatingSystemImpl (null )
170+ : new Target_sun_management_BaseOperatingSystemImpl (null );
171+ osMXBean = SubstrateUtil .cast (osMXBeanImpl , OperatingSystemMXBean .class );
172+ }
173+ return osMXBean ;
143174 }
144175
145176 @ Fold
@@ -251,7 +282,7 @@ synchronized MBeanServer getPlatformMBeanServer() {
251282 /* Modified version of JDK 11: ManagementFactory.getPlatformMBeanServer */
252283 platformMBeanServer = MBeanServerFactory .createMBeanServer ();
253284 for (PlatformManagedObject platformManagedObject : platformManagedObjectsSet ) {
254- addMXBean (platformMBeanServer , platformManagedObject );
285+ addMXBean (platformMBeanServer , handleLazyPlatformManagedObjectSingleton ( platformManagedObject ) );
255286 }
256287 }
257288 return platformMBeanServer ;
@@ -287,7 +318,7 @@ <T extends PlatformManagedObject> T getPlatformMXBean(Class<T> mxbeanInterface)
287318 } else if (result instanceof List ) {
288319 throw new IllegalArgumentException (mxbeanInterface .getName () + " can have more than one instance" );
289320 }
290- return mxbeanInterface .cast (result );
321+ return mxbeanInterface .cast (handleLazyPlatformManagedObjectSingleton ( result ) );
291322 }
292323
293324 @ SuppressWarnings ("unchecked" )
@@ -299,7 +330,33 @@ <T extends PlatformManagedObject> List<T> getPlatformMXBeans(Class<T> mxbeanInte
299330 if (result instanceof List ) {
300331 return (List <T >) result ;
301332 } else {
302- return Collections .singletonList (mxbeanInterface .cast (result ));
333+ return Collections .singletonList (mxbeanInterface .cast (handleLazyPlatformManagedObjectSingleton ( result ) ));
303334 }
304335 }
336+
337+ /**
338+ * A {@link PlatformManagedObject} supplier that is itself a {@link PlatformManagedObject} for
339+ * easier integration with the rest of the {@link ManagementSupport} machinery.
340+ *
341+ * This in particular allows for transparent storage in {@link #platformManagedObjectsMap} and
342+ * {@link #platformManagedObjectsSet} at the expense of
343+ * {@linkplain #handleLazyPlatformManagedObjectSingleton special handling} when retrieving
344+ * stored platform objects.
345+ */
346+ private interface PlatformManagedObjectSupplier extends Supplier <PlatformManagedObject >, PlatformManagedObject {
347+ @ Override
348+ default ObjectName getObjectName () {
349+ throw VMError .shouldNotReachHere ();
350+ }
351+ }
352+
353+ /**
354+ * Provides {@link PlatformManagedObjectSupplier} handling when retrieving singleton platform
355+ * objects from {@link #platformManagedObjectsMap} and {@link #platformManagedObjectsSet}.
356+ */
357+ private static PlatformManagedObject handleLazyPlatformManagedObjectSingleton (Object object ) {
358+ assert object instanceof PlatformManagedObject ;
359+ return object instanceof PlatformManagedObjectSupplier ? ((PlatformManagedObjectSupplier ) object ).get ()
360+ : (PlatformManagedObject ) object ;
361+ }
305362}
0 commit comments