Skip to content

Commit 0340a55

Browse files
committed
Use OperatingSystemMXBean implementation from JDK
1 parent 6d1ee05 commit 0340a55

File tree

5 files changed

+319
-13
lines changed

5 files changed

+319
-13
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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 static com.oracle.svm.core.c.function.CEntryPointOptions.NoEpilogue;
28+
import static com.oracle.svm.core.c.function.CEntryPointOptions.NoPrologue;
29+
import static com.oracle.svm.core.c.function.CEntryPointOptions.Publish;
30+
import static org.graalvm.nativeimage.c.function.CFunction.Transition.NO_TRANSITION;
31+
32+
import org.graalvm.nativeimage.IsolateThread;
33+
import org.graalvm.nativeimage.StackValue;
34+
import org.graalvm.nativeimage.c.function.CEntryPoint;
35+
import org.graalvm.nativeimage.c.function.CFunction;
36+
import org.graalvm.nativeimage.c.function.CLibrary;
37+
import org.graalvm.nativeimage.c.type.CCharPointer;
38+
39+
import com.oracle.svm.core.annotate.Uninterruptible;
40+
import com.oracle.svm.core.c.CGlobalData;
41+
import com.oracle.svm.core.c.CGlobalDataFactory;
42+
import com.oracle.svm.core.c.function.CEntryPointOptions;
43+
import com.oracle.svm.core.headers.LibC;
44+
45+
public final class LibManagementExtSupport {
46+
private static final CGlobalData<CCharPointer> ERRMSG_FORMAT = CGlobalDataFactory.createCString("errno: %d error: %s\n");
47+
48+
/**
49+
* Reimplementation of the native {@code throw_internal_error} function in Java.
50+
*/
51+
@Uninterruptible(reason = "No Java context.")
52+
@CEntryPoint(name = "throw_internal_error", include = CEntryPoint.NotIncludedAutomatically.class)
53+
@CEntryPointOptions(prologue = NoPrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly)
54+
private static void throwInternalError(IsolateThread env, CCharPointer msg) {
55+
/*
56+
* Ported from `src/jdk.management/share/native/libmanagement_ext/management_ext.c`.
57+
*/
58+
CCharPointer errmsg = StackValue.get(128);
59+
60+
sprintf(errmsg, ERRMSG_FORMAT.get(), LibC.errno(), msg);
61+
jnuThrowInternalError(env, errmsg);
62+
}
63+
64+
@CFunction(transition = NO_TRANSITION)
65+
private static native int sprintf(CCharPointer str, CCharPointer format, int errno, CCharPointer msg);
66+
67+
@CLibrary(value = "java", requireStatic = true)
68+
@CFunction(value = "JNU_ThrowInternalError", transition = NO_TRANSITION)
69+
private static native void jnuThrowInternalError(IsolateThread env, CCharPointer msg);
70+
}

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

Lines changed: 70 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;
@@ -48,10 +50,13 @@
4850
import org.graalvm.nativeimage.IsolateThread;
4951
import org.graalvm.nativeimage.Platform;
5052
import org.graalvm.nativeimage.Platforms;
53+
import org.graalvm.nativeimage.impl.InternalPlatform;
5154

55+
import com.oracle.svm.core.SubstrateUtil;
5256
import com.oracle.svm.core.annotate.Uninterruptible;
5357
import com.oracle.svm.core.thread.ThreadListener;
5458
import com.oracle.svm.core.util.UserError;
59+
import com.oracle.svm.core.util.VMError;
5560
import com.sun.jmx.mbeanserver.MXBeanLookup;
5661

5762
/**
@@ -60,15 +65,14 @@
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
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.Substitute;
29+
import com.oracle.svm.core.annotate.TargetClass;
30+
31+
import sun.management.VMManagement;
32+
33+
@TargetClass(className = "com.sun.management.internal.OperatingSystemImpl")
34+
final class Target_com_sun_management_internal_OperatingSystemImpl {
35+
@Substitute
36+
Target_com_sun_management_internal_OperatingSystemImpl(@SuppressWarnings("unused") VMManagement vm) {
37+
/* Workaround until we enable container support (GR-37365). */
38+
SubstrateUtil.cast(this, Target_sun_management_BaseOperatingSystemImpl.class).loadavg = new double[1];
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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.annotate.Alias;
28+
import com.oracle.svm.core.annotate.Substitute;
29+
import com.oracle.svm.core.annotate.TargetClass;
30+
31+
import sun.management.VMManagement;
32+
33+
@SuppressWarnings("static-method")
34+
@TargetClass(className = "sun.management.BaseOperatingSystemImpl")
35+
final class Target_sun_management_BaseOperatingSystemImpl {
36+
@Alias double[] loadavg;
37+
38+
@Alias
39+
Target_sun_management_BaseOperatingSystemImpl(@SuppressWarnings("unused") VMManagement vm) {
40+
}
41+
42+
/*
43+
* The following substitutions eliminate the use of the `BaseOperatingSystemImpl.jvm` field,
44+
* which we set to `null` to avoid dealing with `VMManagementImpl` that we do not support.
45+
*/
46+
@Substitute
47+
public String getName() {
48+
return System.getProperty("os.name");
49+
}
50+
51+
@Substitute
52+
public String getArch() {
53+
return System.getProperty("os.arch");
54+
}
55+
56+
@Substitute
57+
public String getVersion() {
58+
return System.getProperty("os.version");
59+
}
60+
61+
@Substitute
62+
public int getAvailableProcessors() {
63+
return Runtime.getRuntime().availableProcessors();
64+
}
65+
}

0 commit comments

Comments
 (0)