Skip to content

Commit dd8b425

Browse files
committed
Use OperatingSystemMXBean implementation from JDK
1 parent f9322cc commit dd8b425

File tree

3 files changed

+185
-13
lines changed

3 files changed

+185
-13
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package com.oracle.svm.core.jdk.management;
2626

2727
import java.lang.management.ManagementFactory;
28+
import java.lang.management.OperatingSystemMXBean;
2829
import java.lang.management.PlatformManagedObject;
2930
import java.util.ArrayList;
3031
import java.util.Collections;
@@ -33,6 +34,7 @@
3334
import java.util.List;
3435
import java.util.Map;
3536
import java.util.Set;
37+
import java.util.function.Supplier;
3638

3739
import javax.management.DynamicMBean;
3840
import javax.management.JMException;
@@ -49,9 +51,11 @@
4951
import org.graalvm.nativeimage.Platform;
5052
import org.graalvm.nativeimage.Platforms;
5153

54+
import com.oracle.svm.core.SubstrateUtil;
5255
import com.oracle.svm.core.annotate.Uninterruptible;
5356
import com.oracle.svm.core.thread.ThreadListener;
5457
import com.oracle.svm.core.util.UserError;
58+
import com.oracle.svm.core.util.VMError;
5559
import com.sun.jmx.mbeanserver.MXBeanLookup;
5660

5761
/**
@@ -60,15 +64,14 @@
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
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2022, 2022, 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.oracle.svm.core.jdk.management;
26+
27+
import com.oracle.svm.core.SubstrateUtil;
28+
import com.oracle.svm.core.annotate.Alias;
29+
import com.oracle.svm.core.annotate.Substitute;
30+
import com.oracle.svm.core.annotate.TargetClass;
31+
32+
import sun.management.VMManagement;
33+
34+
@TargetClass(className = "com.sun.management.internal.OperatingSystemImpl")
35+
final class Target_com_sun_management_internal_OperatingSystemImpl {
36+
@Substitute
37+
Target_com_sun_management_internal_OperatingSystemImpl(@SuppressWarnings("unused") VMManagement vm) {
38+
/* Workaround until we enable container support (GR-37365). */
39+
SubstrateUtil.cast(this, Target_sun_management_BaseOperatingSystemImpl.class).loadavg = new double[1];
40+
}
41+
}
42+
43+
@SuppressWarnings("static-method")
44+
@TargetClass(className = "sun.management.BaseOperatingSystemImpl")
45+
final class Target_sun_management_BaseOperatingSystemImpl {
46+
@Alias double[] loadavg;
47+
48+
/*
49+
* The following substitutions eliminate the use of the `BaseOperatingSystemImpl.jvm` field,
50+
* which we set to `null` to avoid dealing with `VMManagementImpl` that we do not support.
51+
*/
52+
@Substitute
53+
public String getName() {
54+
return System.getProperty("os.name");
55+
}
56+
57+
@Substitute
58+
public String getArch() {
59+
return System.getProperty("os.arch");
60+
}
61+
62+
@Substitute
63+
public String getVersion() {
64+
return System.getProperty("os.version");
65+
}
66+
67+
@Substitute
68+
public int getAvailableProcessors() {
69+
return Runtime.getRuntime().availableProcessors();
70+
}
71+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2022, 2022, 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.oracle.svm.hosted.jdk;
26+
27+
import org.graalvm.nativeimage.hosted.Feature;
28+
29+
import com.oracle.svm.core.annotate.AutomaticFeature;
30+
import com.oracle.svm.core.jdk.JNIRegistrationUtil;
31+
import com.oracle.svm.core.jdk.NativeLibrarySupport;
32+
import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport;
33+
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
34+
35+
@AutomaticFeature
36+
public class JNIRegistrationManagementExt extends JNIRegistrationUtil implements Feature {
37+
@Override
38+
public void beforeAnalysis(BeforeAnalysisAccess access) {
39+
rerunClassInit(access, "com.sun.management.internal.OperatingSystemImpl");
40+
41+
access.registerReachabilityHandler(JNIRegistrationManagementExt::linkManagementExt,
42+
clazz(access, "com.sun.management.internal.OperatingSystemImpl"));
43+
PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("com_sun_management_internal_OperatingSystemImpl");
44+
}
45+
46+
private static void linkManagementExt(DuringAnalysisAccess a) {
47+
var access = (DuringAnalysisAccessImpl) a;
48+
NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("management_ext");
49+
access.getNativeLibraries().addStaticJniLibrary("management_ext");
50+
if (isWindows()) {
51+
access.getNativeLibraries().addDynamicNonJniLibrary("psapi");
52+
}
53+
}
54+
}

0 commit comments

Comments
 (0)