From 3b1ef935a523164db02e7fd4002c4e9641461439 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 14 Nov 2022 16:47:09 +0100 Subject: [PATCH 1/6] Add initial support for JMX to Native Image. Co-authored-by: Fabio Niephaus --- substratevm/CHANGELOG.md | 1 + substratevm/mx.substratevm/suite.py | 12 + .../oracle/svm/core/genscavenge/GCImpl.java | 15 + .../oracle/svm/core/genscavenge/HeapImpl.java | 5 + .../oracle/svm/core/VMInspectionOptions.java | 18 +- .../src/com/oracle/svm/core/heap/Heap.java | 3 + .../jdk/management/JmxClientNotIncluded.java | 37 ++ .../svm/core/jdk/management/JmxIncluded.java | 38 ++ .../jdk/management/JmxServerIncluded.java | 38 ++ .../ManagementAgentStartupHook.java | 41 +++ .../jdk/management/ManagementSupport.java | 33 ++ ...ava_lang_management_ManagementFactory.java | 8 +- ...management_remote_JMXConnectorFactory.java | 54 +++ .../Target_jdk_internal_agent_Agent.java | 90 +++++ .../Target_jdk_internal_vm_VMSupport.java | 51 +++ .../Target_sun_rmi_transport_GC.java | 42 +++ .../svm/hosted/jdk/JmxClientFeature.java | 297 ++++++++++++++++ .../svm/hosted/jdk/JmxServerFeature.java | 336 ++++++++++++++++++ .../native-image.properties | 2 +- .../src/com/oracle/svm/test/jmx/JmxTest.java | 308 ++++++++++++++++ .../src/com/oracle/svm/test/jmx/Simple.java | 43 +++ .../com/oracle/svm/test/jmx/SimpleMBean.java | 34 ++ 22 files changed, 1498 insertions(+), 8 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxClientNotIncluded.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxIncluded.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxServerIncluded.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementAgentStartupHook.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_javax_management_remote_JMXConnectorFactory.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_agent_Agent.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_vm_VMSupport.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_sun_rmi_transport_GC.java create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java create mode 100644 substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/JmxTest.java create mode 100644 substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/Simple.java create mode 100644 substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/SimpleMBean.java diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index 573cbe3ca392..c3dd40e35d8d 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -9,6 +9,7 @@ This changelog summarizes major changes to GraalVM Native Image. * (GR-41674) Class instanceOf and isAssignableFrom checks do need to make the checked type reachable. * (GR-41100) Add support for `-XX:HeapDumpPath` to control where heap dumps are created. * (GR-42148) Adjust build output to report types (primitives, classes, interfaces, and arrays) instead of classes and revise the output schema of `-H:BuildOutputJSONFile`. +* (GR-40463) Red Hat added initial support for JMX, which can be enabled with the `--enable-monitoring` option (e.g. `--enable-monitoring=jmxclient,jmxserver`). ## Version 22.3.0 * (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option. diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index e5fa7145ca65..d9983af05f97 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -262,6 +262,7 @@ "jdk.internal.perf", "jdk.internal.ref", "jdk.internal.reflect", + "jdk.internal.vm", "jdk.internal.util", ], "java.desktop": [ @@ -275,6 +276,12 @@ "jdk.management": [ "com.sun.management.internal" ], + "jdk.management.agent": [ + "jdk.internal.agent", + ], + "jdk.management.jfr": [ + "jdk.management.jfr" + ], "jdk.httpserver@19+": [ "sun.net.httpserver.simpleserver", ], @@ -797,6 +804,9 @@ "requires": [ "java.compiler", "jdk.jfr", + "java.management", + "jdk.management.jfr", + "java.rmi", ], "requiresConcealed" : { "java.base" : [ @@ -1262,6 +1272,8 @@ "java.net.http", "jdk.sctp", "jdk.scripting.nashorn@11..14", + "jdk.management.agent", + "jdk.management.jfr", ], "uses" : [ "org.graalvm.nativeimage.Platform", diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index 26d08386c654..974a20b593df 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -115,6 +115,7 @@ public final class GCImpl implements GC { private UnsignedWord sizeBefore = WordFactory.zero(); private boolean collectionInProgress = false; private UnsignedWord collectionEpoch = WordFactory.zero(); + private long lastWholeHeapExaminedTimeNs = -1; @Platforms(Platform.HOSTED_ONLY.class) GCImpl() { @@ -287,6 +288,9 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co } scavenge(!complete); verifyAfterGC(); + if (complete) { + lastWholeHeapExaminedTimeNs = System.nanoTime(); + } } finally { collectionTimer.close(); } @@ -1179,6 +1183,17 @@ public UnsignedWord getCollectionEpoch() { return collectionEpoch; } + /** + * Returns the time in ns that the last full GC happened relative to when the program was + * started. If no full GC has yet been run, it returns the time since the first allocation. + */ + public long getLastWholeHeapExaminedTimeNs() { + if (lastWholeHeapExaminedTimeNs < 0) { + return HeapImpl.getChunkProvider().getFirstAllocationTime(); + } + return lastWholeHeapExaminedTimeNs; + } + public GCAccounting getAccounting() { return accounting; } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java index 69f4b5373efb..f83435053e1b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java @@ -686,6 +686,11 @@ public void dirtyAllReferencesOf(Object obj) { } } + @Override + public long getMaxObjectInspectionAge() { + return (System.nanoTime() - getGCImpl().getLastWholeHeapExaminedTimeNs()) / 1000000; + } + static Pointer getImageHeapStart() { int imageHeapOffsetInAddressSpace = Heap.getHeap().getImageHeapOffsetInAddressSpace(); if (imageHeapOffsetInAddressSpace > 0) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspectionOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspectionOptions.java index f0778145c83a..7258dfe2c711 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspectionOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspectionOptions.java @@ -48,8 +48,10 @@ public final class VMInspectionOptions { private static final String MONITORING_HEAPDUMP_NAME = "heapdump"; private static final String MONITORING_JFR_NAME = "jfr"; private static final String MONITORING_JVMSTAT_NAME = "jvmstat"; - private static final String MONITORING_ALLOWED_VALUES = "'" + MONITORING_HEAPDUMP_NAME + "', '" + MONITORING_JFR_NAME + "', '" + MONITORING_JVMSTAT_NAME + "', or '" + MONITORING_ALL_NAME + - "' (defaults to '" + MONITORING_ALL_NAME + "' if no argument is provided)"; + private static final String MONITORING_JMXCLIENT_NAME = "jmxclient"; + private static final String MONITORING_JMXSERVER_NAME = "jmxserver"; + private static final String MONITORING_ALLOWED_VALUES = "'" + MONITORING_HEAPDUMP_NAME + "', '" + MONITORING_JFR_NAME + "', '" + MONITORING_JVMSTAT_NAME + "', '" + MONITORING_JMXSERVER_NAME + + "', '" + MONITORING_JMXCLIENT_NAME + "', or '" + MONITORING_ALL_NAME + "' (defaults to '" + MONITORING_ALL_NAME + "' if no argument is provided)"; @APIOption(name = ENABLE_MONITORING_OPTION, defaultValue = MONITORING_ALL_NAME) // @Option(help = "Enable monitoring features that allow the VM to be inspected at run time. Comma-separated list can contain " + MONITORING_ALLOWED_VALUES + ". " + @@ -59,7 +61,7 @@ public final class VMInspectionOptions { public static void validateEnableMonitoringFeatures(OptionKey optionKey) { Set enabledFeatures = getEnabledMonitoringFeatures(); - enabledFeatures.removeAll(List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_ALL_NAME)); + enabledFeatures.removeAll(List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_JMXCLIENT_NAME, MONITORING_JMXSERVER_NAME, MONITORING_ALL_NAME)); if (!enabledFeatures.isEmpty()) { throw UserError.abort("The option %s contains invalid value(s): %s. It can only contain %s.", optionKey.getName(), String.join(", ", enabledFeatures), MONITORING_ALLOWED_VALUES); } @@ -94,6 +96,16 @@ public static boolean hasJvmstatSupport() { return hasAllOrKeywordMonitoringSupport(MONITORING_JVMSTAT_NAME) && !Platform.includedIn(WINDOWS.class); } + @Fold + public static boolean hasJmxServerSupport() { + return hasAllOrKeywordMonitoringSupport(MONITORING_JMXSERVER_NAME) && !Platform.includedIn(WINDOWS.class); + } + + @Fold + public static boolean hasJmxClientSupport() { + return hasAllOrKeywordMonitoringSupport(MONITORING_JMXCLIENT_NAME) && !Platform.includedIn(WINDOWS.class); + } + @Option(help = "Dumps all runtime compiled methods on SIGUSR2.", type = OptionType.User) // public static final HostedOptionKey DumpRuntimeCompilationOnSignal = new HostedOptionKey<>(false, VMInspectionOptions::validateOnSignalOption); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java index c400b566a974..9b9309fc9467 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java @@ -244,4 +244,7 @@ public List> getLoadedClasses() { /** Consider all references in the given object as needing remembered set entries. */ @Uninterruptible(reason = "Ensure that no GC can occur between modification of the object and this call.", callerMustBe = true) public abstract void dirtyAllReferencesOf(Object obj); + + /** Returns time since the last full GC in milliseconds. */ + public abstract long getMaxObjectInspectionAge(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxClientNotIncluded.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxClientNotIncluded.java new file mode 100644 index 000000000000..36c2dd3c992a --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxClientNotIncluded.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.core.jdk.management; + +import java.util.function.BooleanSupplier; +import com.oracle.svm.core.VMInspectionOptions; + +public class JmxClientNotIncluded implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return !VMInspectionOptions.hasJmxClientSupport(); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxIncluded.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxIncluded.java new file mode 100644 index 000000000000..f89847419bbe --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxIncluded.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.core.jdk.management; + +import java.util.function.BooleanSupplier; + +import com.oracle.svm.core.VMInspectionOptions; + +public class JmxIncluded implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return VMInspectionOptions.hasJmxServerSupport() || VMInspectionOptions.hasJmxClientSupport(); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxServerIncluded.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxServerIncluded.java new file mode 100644 index 000000000000..dc2eeae6d0bb --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/JmxServerIncluded.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.core.jdk.management; + +import java.util.function.BooleanSupplier; + +import com.oracle.svm.core.VMInspectionOptions; + +public class JmxServerIncluded implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return VMInspectionOptions.hasJmxServerSupport(); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementAgentStartupHook.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementAgentStartupHook.java new file mode 100644 index 000000000000..3e32649c4496 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementAgentStartupHook.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.core.jdk.management; + +import com.oracle.svm.core.util.VMError; + +public class ManagementAgentStartupHook implements com.oracle.svm.core.jdk.RuntimeSupport.Hook { + + @Override + public void execute(boolean isFirstIsolate) { + try { + jdk.internal.agent.Agent.startAgent(); + } catch (Exception e) { + throw VMError.shouldNotReachHere("ManagementFeature start-up hook failed: " + e); + } + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java index 2b25fa461d9e..ed0d09bdacb1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java @@ -45,6 +45,7 @@ import javax.management.StandardEmitterMBean; import javax.management.StandardMBean; +import jdk.management.jfr.FlightRecorderMXBean; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; @@ -53,10 +54,13 @@ import org.graalvm.nativeimage.impl.InternalPlatform; import com.oracle.svm.core.SubstrateUtil; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.thread.ThreadListener; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; +import com.oracle.svm.core.jfr.HasJfrSupport; import com.sun.jmx.mbeanserver.MXBeanLookup; /** @@ -119,6 +123,7 @@ public final class ManagementSupport implements ThreadListener { /* Initialized lazily at run time. */ private OperatingSystemMXBean osMXBean; + private FlightRecorderMXBean flightRecorderMXBean; /** The singleton MBean server for the platform, initialized lazily at run time. */ MBeanServer platformMBeanServer; @@ -152,6 +157,8 @@ public final class ManagementSupport implements ThreadListener { * run time. */ doAddPlatformManagedObjectSingleton(getOsMXBeanInterface(), (PlatformManagedObjectSupplier) this::getOsMXBean); + doAddPlatformManagedObjectSingleton(FlightRecorderMXBean.class, (PlatformManagedObjectSupplier) this::getFlightRecorderMXBean); + } private static Class getOsMXBeanInterface() { @@ -173,6 +180,16 @@ private synchronized OperatingSystemMXBean getOsMXBean() { return osMXBean; } + private synchronized FlightRecorderMXBean getFlightRecorderMXBean() { + if (!HasJfrSupport.get()) { + return null; + } + if (flightRecorderMXBean == null) { + flightRecorderMXBean = SubstrateUtil.cast(new Target_jdk_management_jfr_FlightRecorderMXBeanImpl(), FlightRecorderMXBean.class); + } + return flightRecorderMXBean; + } + @Fold public static ManagementSupport getSingleton() { return ImageSingletons.lookup(ManagementSupport.class); @@ -290,6 +307,9 @@ synchronized MBeanServer getPlatformMBeanServer() { /* Modified version of JDK 11: ManagementFactory.addMXBean */ private static void addMXBean(MBeanServer mbs, PlatformManagedObject pmo) { + if (pmo == null) { + return; + } ObjectName oname = pmo.getObjectName(); // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean final DynamicMBean dmbean; @@ -311,6 +331,11 @@ Set> getPlatformManagementInterfaces() { return Collections.unmodifiableSet(platformManagedObjectsMap.keySet()); } + @Platforms(Platform.HOSTED_ONLY.class) + public Set getPlatformManagedObjects() { + return platformManagedObjectsSet; + } + T getPlatformMXBean(Class mxbeanInterface) { Object result = platformManagedObjectsMap.get(mxbeanInterface); if (result == null) { @@ -360,3 +385,11 @@ private static PlatformManagedObject handleLazyPlatformManagedObjectSingleton(Ob : (PlatformManagedObject) object; } } + +// This is required because FlightRecorderMXBeanImpl is only accessible within its package. +@TargetClass(className = "jdk.management.jfr.FlightRecorderMXBeanImpl") +final class Target_jdk_management_jfr_FlightRecorderMXBeanImpl { + @Alias + Target_jdk_management_jfr_FlightRecorderMXBeanImpl() { + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_java_lang_management_ManagementFactory.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_java_lang_management_ManagementFactory.java index 16a5a8ca8857..2ec4fb14a1bb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_java_lang_management_ManagementFactory.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_java_lang_management_ManagementFactory.java @@ -34,6 +34,7 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; /** See {@link ManagementSupport} for documentation. */ @TargetClass(java.lang.management.ManagementFactory.class) @@ -60,21 +61,20 @@ static List getPlatformMXBeans(Class mxb return ManagementSupport.getSingleton().getPlatformMXBeans(mxbeanInterface); } - /* - * Connections to remote MBean servers are not yet supported. - */ - @Substitute + @TargetElement(onlyWith = JmxClientNotIncluded.class) private static T getPlatformMXBean(MBeanServerConnection connection, Class mxbeanInterface) throws java.io.IOException { return null; } @Substitute + @TargetElement(onlyWith = JmxClientNotIncluded.class) private static List getPlatformMXBeans(MBeanServerConnection connection, Class mxbeanInterface) throws java.io.IOException { return Collections.emptyList(); } @Substitute + @TargetElement(onlyWith = JmxClientNotIncluded.class) private static T newPlatformMXBeanProxy(MBeanServerConnection connection, String mxbeanName, Class mxbeanInterface) throws java.io.IOException { return null; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_javax_management_remote_JMXConnectorFactory.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_javax_management_remote_JMXConnectorFactory.java new file mode 100644 index 000000000000..c505cf0629ae --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_javax_management_remote_JMXConnectorFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.core.jdk.management; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; + +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import java.io.IOException; +import java.util.Map; + +@TargetClass(JMXConnectorFactory.class) +@SuppressWarnings("unused") +final class Target_javax_management_remote_JMXConnectorFactory { + + @Substitute + @TargetElement(onlyWith = JmxClientNotIncluded.class) + public static JMXConnector connect(JMXServiceURL serviceURL) throws IOException { + return null; + } + + @Substitute + @TargetElement(onlyWith = JmxClientNotIncluded.class) + public static JMXConnector connect(JMXServiceURL serviceURL, Map environment) throws IOException { + return null; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_agent_Agent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_agent_Agent.java new file mode 100644 index 000000000000..8e52ed52fe4d --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_agent_Agent.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.jdk.management; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; +import jdk.internal.agent.Agent; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; + +import java.util.Properties; + +import static jdk.internal.agent.AgentConfigurationError.CONFIG_FILE_NOT_FOUND; +import static jdk.internal.agent.AgentConfigurationError.CONFIG_FILE_OPEN_FAILED; +import static jdk.internal.agent.AgentConfigurationError.CONFIG_FILE_ACCESS_DENIED; +import static jdk.internal.agent.AgentConfigurationError.CONFIG_FILE_CLOSE_FAILED; + +@TargetClass(jdk.internal.agent.Agent.class) +final class Target_jdk_internal_agent_Agent { + + /** + * This method is substituted to avoid throwing an exception if java.home is null. If a config + * file is not specified via com.sun.management.config.file=ConfigFilePath, AND java.home is not + * set, then this method doesn't bother trying to read from config file. + * + * This method is mostly copied (aside from a single line change) from jdk19. Commit hash + * 967a28c3d85fdde6d5eb48aa0edd8f7597772469. + */ + @Substitute + @TargetElement(onlyWith = JmxServerIncluded.class) + public static void readConfiguration(String fname, Properties p) { + if (fname == null) { + // if file is not specified, don't bother trying to read from a management.properties + // file. + return; + } + final File configFile = new File(fname); + if (!configFile.exists()) { + Agent.error(CONFIG_FILE_NOT_FOUND, fname); + } + + InputStream in = null; + try { + in = new FileInputStream(configFile); + p.load(in); + } catch (FileNotFoundException e) { + Agent.error(CONFIG_FILE_OPEN_FAILED, e.getMessage()); + } catch (IOException e) { + Agent.error(CONFIG_FILE_OPEN_FAILED, e.getMessage()); + } catch (SecurityException e) { + Agent.error(CONFIG_FILE_ACCESS_DENIED, fname); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + Agent.error(CONFIG_FILE_CLOSE_FAILED, fname); + } + } + } + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_vm_VMSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_vm_VMSupport.java new file mode 100644 index 000000000000..f9ca0dc1d1b4 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_jdk_internal_vm_VMSupport.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.core.jdk.management; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; + +import java.util.Properties; +import com.oracle.svm.core.JavaMainWrapper.JavaMainSupport; +import org.graalvm.nativeimage.ImageSingletons; + +@TargetClass(jdk.internal.vm.VMSupport.class) +final class Target_jdk_internal_vm_VMSupport { + + @Substitute + @TargetElement(onlyWith = JmxServerIncluded.class) + private static Properties initAgentProperties(Properties properties) { + if (ImageSingletons.contains(JavaMainSupport.class)) { + JavaMainSupport support = ImageSingletons.lookup(JavaMainSupport.class); + properties.setProperty("sun.jvm.args", support.getJavaCommand()); + properties.setProperty("sun.jvm.flags", ""); + properties.setProperty("sun.java.command", support.getJavaCommand()); + } + return properties; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_sun_rmi_transport_GC.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_sun_rmi_transport_GC.java new file mode 100644 index 000000000000..74fe617ccba2 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/Target_sun_rmi_transport_GC.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.core.jdk.management; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.annotate.TargetElement; + +import com.oracle.svm.core.heap.Heap; + +@TargetClass(className = "sun.rmi.transport.GC") +final class Target_sun_rmi_transport_GC { + @Substitute + @TargetElement(onlyWith = JmxIncluded.class) + public static long maxObjectInspectionAge() { + return Heap.getHeap().getMaxObjectInspectionAge(); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java new file mode 100644 index 000000000000..f0c07815b6b2 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted.jdk; + +import java.util.Arrays; + +import org.graalvm.nativeimage.ImageSingletons; +import com.oracle.svm.core.feature.InternalFeature; +import org.graalvm.nativeimage.hosted.RuntimeReflection; + +import com.oracle.svm.core.jdk.JNIRegistrationUtil; +import com.oracle.svm.core.util.VMError; + +import com.oracle.svm.core.jdk.NativeLibrarySupport; +import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; +import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; +import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; +import com.oracle.svm.core.jni.JNIRuntimeAccess; +import org.graalvm.nativeimage.hosted.RuntimeSerialization; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.VMInspectionOptions; +import com.oracle.svm.util.ReflectionUtil; + +@AutomaticallyRegisteredFeature +public class JmxClientFeature extends JNIRegistrationUtil implements InternalFeature { + @Override + public boolean isInConfiguration(IsInConfigurationAccess access) { + return VMInspectionOptions.hasJmxClientSupport(); + } + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport rci = ImageSingletons.lookup(org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport.class); + if (org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC <= 11) { + // Activation has been removed in JDK 17. + rci.initializeAtBuildTime("sun.rmi.server.Activation$ActivationSystemImpl_Stub", "JDK11 JMX support"); + } + + rci.initializeAtBuildTime("jdk.management.jfr.SettingDescriptorInfo", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log$LogStreamLog", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log", "JMX support"); + rci.initializeAtBuildTime("java.rmi.server.LogStream", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log$LoggerLog", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.server.Util", "JMX support"); + rci.initializeAtBuildTime("jdk.management.jfr.MBeanUtils", "JMX support"); + + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.StandardMBeanIntrospector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanLookup", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp", "JMX support"); + rci.initializeAtBuildTime("java.rmi.server.RemoteObjectInvocationHandler", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector", "JMX support"); + rci.initializeAtBuildTime("java.beans.Introspector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.JavaBeansAccessor", "JMX support"); + + rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MBeanInstantiator", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ArrayNotificationBuffer", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.security.HashedPasswordManager", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXSubjectDomainCombiner", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerCommunicatorAdmin", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.defaults.JmxProperties", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerNotifForwarder", "JMX support"); + + rci.initializeAtRunTime("sun.rmi.transport.ConnectionInputStream", "JMX support"); + rci.initializeAtRunTime("java.rmi.MarshalledObject$MarshalledObjectInputStream", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastRef2", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastRef", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.MarshalInputStream", "JMX support"); + rci.initializeAtRunTime("sun.rmi.runtime.NewThreadAction", "JMX support"); + rci.initializeAtRunTime("com.sun.jmx.remote.security.FileLoginModule", "JMX support"); + rci.initializeAtRunTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator$FileLoginConfig", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCImpl", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCAckHandler", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.GC", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCClient", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.ObjectTable", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPEndpoint", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPChannel", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPTransport", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.Transport", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.ObjID", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.UID", "JMX support"); + rci.initializeAtRunTime("sun.rmi.runtime.RuntimeUtil", "JMX support"); + rci.initializeAtRunTime("java.rmi.dgc.VMID", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.RMIClassLoader", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.LoaderHandler", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.RemoteServer", "JMX support"); + rci.initializeAtRunTime("sun.rmi.registry.RegistryImpl", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.UnicastRemoteObject", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef2", "JMX support"); + } + + private static void handleNativeLibraries(BeforeAnalysisAccess access) { + BeforeAnalysisAccessImpl a = (BeforeAnalysisAccessImpl) access; + NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("rmi"); + a.getNativeLibraries().addStaticJniLibrary("rmi"); + + // Resolve calls to sun_rmi_transport* as builtIn. For calls to native method + // maxObjectInspectionAge() + PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_rmi_transport"); + } + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + try { + configureProxy(access); + configureJNI(); + configureSerialization(access); + configureReflection(access); + handleNativeLibraries(access); + } catch (Exception e) { + throw VMError.shouldNotReachHere("ManagementClientFeature configuration failed: " + e); + } + } + + private static void configureProxy(BeforeAnalysisAccess access) { + DynamicProxyRegistry dynamicProxySupport = ImageSingletons.lookup(DynamicProxyRegistry.class); + + dynamicProxySupport.addProxyClass(access.findClassByName("jdk.management.jfr.FlightRecorderMXBean"), + access.findClassByName("javax.management.NotificationEmitter")); + + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.RuntimeMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ClassLoadingMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryManagerMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.BufferPoolMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryPoolMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.UnixOperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.java.lang.management.CompilationMXBean")); + } + + private static void configureJNI() { + JNIRuntimeAccess.register(Arrays.class); + JNIRuntimeAccess.register(ReflectionUtil.lookupMethod(Arrays.class, "asList", Object[].class)); + JNIRuntimeAccess.register(Boolean.class); + JNIRuntimeAccess.register(ReflectionUtil.lookupMethod(Boolean.class, "getBoolean", String.class)); + } + + // seems like the serialization is the same for both client and server, maybe we + // can reduce code duplication. + private static void configureSerialization(BeforeAnalysisAccess access) { + String[] classes = new String[]{ + "[B", "com.oracle.svm.core.jdk.UnsupportedFeatureError", + "java.io.IOException", "java.lang.Boolean", "java.lang.ClassCastException", "java.lang.Error", + "java.lang.Exception", "java.lang.IllegalArgumentException", "java.lang.IllegalStateException", + "java.lang.Integer", "[Ljava.lang.Integer;", "java.lang.Long", "java.lang.NoSuchMethodException", + "java.lang.Number", "[Ljava.lang.Object;", "java.lang.ReflectiveOperationException", + "java.lang.RuntimeException", "java.lang.SecurityException", "java.lang.StackTraceElement", + "[Ljava.lang.StackTraceElement;", "java.lang.String", "java.lang.Throwable", + "java.lang.UnsupportedOperationException", + "java.rmi.MarshalledObject", "[Ljava.rmi.MarshalledObject;", "java.rmi.RemoteException", + "java.rmi.ServerError", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", "java.rmi.server.ObjID", + "[Ljava.rmi.server.ObjID;", "java.rmi.server.RemoteObject", "java.rmi.server.RemoteStub", + "java.rmi.server.UID", "java.security.GeneralSecurityException", "java.util.ArrayList", + "java.util.Arrays$ArrayList", "java.util.Collections$EmptyList", + "java.util.Collections$UnmodifiableCollection", "java.util.Collections$UnmodifiableList", + "java.util.Collections$UnmodifiableRandomAccessList", + "java.util.EventObject", // Required for notifications + "java.util.HashMap", "java.util.HashSet", + "java.util.LinkedHashMap", "java.util.MissingResourceException", "java.util.TreeMap", + "java.util.Vector", "javax.management.Attribute", "javax.management.AttributeList", + "javax.management.AttributeNotFoundException", + "javax.management.AttributeChangeNotification", // Required for + // notifications + "javax.management.InstanceNotFoundException", + "javax.management.JMException", "javax.management.MBeanAttributeInfo", + "[Ljavax.management.MBeanAttributeInfo;", "[Ljavax.management.MBeanConstructorInfo;", + "javax.management.MBeanFeatureInfo", "javax.management.MBeanInfo", + "javax.management.MBeanNotificationInfo", "[Ljavax.management.MBeanNotificationInfo;", + "javax.management.MBeanOperationInfo", "[Ljavax.management.MBeanOperationInfo;", + "javax.management.MBeanParameterInfo", "[Ljavax.management.MBeanParameterInfo;", + "javax.management.Notification", // Required for notifications + "javax.management.NotificationFilterSupport", "javax.management.ObjectName", + "[Ljavax.management.ObjectName;", "javax.management.OperationsException", "javax.management.ReflectionException", + "javax.management.openmbean.ArrayType", "javax.management.openmbean.CompositeDataSupport", + "[Ljavax.management.openmbean.CompositeData;", "javax.management.openmbean.CompositeType", + "javax.management.openmbean.OpenMBeanAttributeInfoSupport", + "javax.management.openmbean.OpenMBeanParameterInfoSupport", "javax.management.openmbean.OpenType", + "javax.management.openmbean.SimpleType", "javax.management.openmbean.TabularDataSupport", + "javax.management.openmbean.TabularType", "javax.management.remote.NotificationResult", + "javax.management.remote.TargetedNotification", // Required for + // notifications + "[Ljavax.management.remote.TargetedNotification;", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServerImpl_Stub", "javax.management.RuntimeMBeanException", + "javax.rmi.ssl.SslRMIClientSocketFactory", // Required for SSL + "[Ljavax.security.auth.Subject;", "javax.security.auth.login.FailedLoginException", + "javax.security.auth.login.LoginException", "[J", "java.rmi.NoSuchObjectException", + "javax.management.JMRuntimeException", "javax.management.RuntimeErrorException" + }; + + for (String clazz : classes) { + RuntimeSerialization.register(access.findClassByName(clazz)); + } + } + + private static void configureReflection(BeforeAnalysisAccess access) { + String[] classes = new String[]{ + "com.sun.crypto.provider.AESCipher$General", + "com.sun.crypto.provider.ARCFOURCipher", "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "com.sun.crypto.provider.DESCipher", "com.sun.crypto.provider.DESedeCipher", + "com.sun.crypto.provider.DHParameters", + "com.sun.crypto.provider.HmacCore$HmacSHA256", + "com.sun.jndi.url.rmi.rmiURLContextFactory", // Unique to client + "com.sun.management.GcInfo", "com.sun.management.VMOption", + "com.sun.management.internal.OperatingSystemImpl", "java.rmi.MarshalledObject", "java.rmi.Remote", + "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", "java.rmi.registry.Registry", "java.rmi.server.ObjID", + "java.rmi.server.RemoteObject", "java.rmi.server.RemoteStub", "java.rmi.server.UID", + "java.lang.management.LockInfo", "java.lang.management.ManagementPermission", + "java.lang.management.MemoryUsage", "java.lang.management.MonitorInfo", + "java.lang.management.ThreadInfo", "java.security.SecureRandomParameters", + "javax.management.MBeanServerBuilder", "javax.management.NotificationBroadcaster", + "javax.management.NotificationEmitter", "javax.management.NotificationFilterSupport", + "javax.management.ObjectName", "javax.management.openmbean.OpenType", + "javax.management.remote.rmi.RMIConnection", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServer", "javax.management.remote.rmi.RMIServerImpl_Stub", + "jdk.management.jfr.FlightRecorderMXBean", "jdk.management.jfr.ConfigurationInfo", + "jdk.management.jfr.EventTypeInfo", "jdk.management.jfr.RecordingInfo", + "jdk.management.jfr.SettingDescriptorInfo", "sun.rmi.registry.RegistryImpl_Skel", + "sun.rmi.registry.RegistryImpl_Stub", "sun.rmi.server.UnicastRef2", + "sun.rmi.server.UnicastRef", // Unique to client + "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", "sun.rmi.transport.DGCImpl_Skel", + "sun.rmi.transport.DGCImpl_Stub" + }; + + String[] methods = new String[]{ + "com.sun.management.GcInfo", "com.sun.management.VMOption", + "java.rmi.registry.Registry", "jdk.management.jfr.FlightRecorderMXBean", + "java.lang.management.MemoryUsage", "java.lang.management.MonitorInfo", + "java.lang.management.ThreadInfo", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServer", "javax.management.remote.rmi.RMIServerImpl_Stub", + "javax.management.remote.rmi.RMIConnection", "javax.management.remote.rmi.RMIConnection", + "jdk.management.jfr.ConfigurationInfo", "jdk.management.jfr.EventTypeInfo", + "jdk.management.jfr.RecordingInfo", "jdk.management.jfr.SettingDescriptorInfo", + "sun.rmi.registry.RegistryImpl_Stub", "sun.rmi.server.UnicastRef2", "sun.rmi.server.UnicastRef", + "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", "sun.rmi.transport.DGCImpl_Stub" + }; + + String[] fields = new String[]{"com.sun.management.GcInfo"}; + + String[] constructors = new String[]{"com.sun.jndi.url.rmi.rmiURLContextFactory", + "com.sun.management.internal.GarbageCollectorExtImpl", + "com.sun.management.internal.OperatingSystemImpl", "java.lang.management.ManagementPermission", + "javax.management.MBeanServerBuilder", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.transport.DGCImpl_Stub", + "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.registry.RegistryImpl_Stub", + "sun.rmi.server.UnicastRef2", "sun.rmi.server.UnicastRef", "sun.rmi.transport.DGCImpl_Skel" + }; + + for (String clazz : classes) { + Class c = access.findClassByName(clazz); + if (c == null) { + continue; + } + RuntimeReflection.register(c); + } + for (String clazz : methods) { + RuntimeReflection.register(access.findClassByName(clazz).getMethods()); + } + for (String clazz : constructors) { + RuntimeReflection.register(access.findClassByName(clazz).getConstructors()); + } + for (String clazz : fields) { + RuntimeReflection.register(access.findClassByName(clazz).getFields()); + } + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java new file mode 100644 index 000000000000..ca4daf7ee3cc --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.hosted.jdk; + +import com.oracle.svm.core.feature.InternalFeature; + +import java.lang.management.PlatformManagedObject; +import java.util.Arrays; + +import java.util.Set; + +import com.oracle.svm.core.jdk.NativeLibrarySupport; +import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; +import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; +import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.ImageSingletons; +import com.oracle.svm.core.configure.ResourcesRegistry; +import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; +import com.oracle.svm.core.jni.JNIRuntimeAccess; +import org.graalvm.nativeimage.hosted.RuntimeReflection; +import org.graalvm.nativeimage.hosted.RuntimeSerialization; +import com.oracle.svm.core.jdk.RuntimeSupport; +import com.oracle.svm.core.jdk.management.ManagementAgentStartupHook; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.VMInspectionOptions; +import com.oracle.svm.util.ReflectionUtil; + +@AutomaticallyRegisteredFeature +public class JmxServerFeature implements InternalFeature { + @Override + public boolean isInConfiguration(IsInConfigurationAccess access) { + return VMInspectionOptions.hasJmxServerSupport(); + } + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport rci = ImageSingletons.lookup(org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport.class); + if (org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC <= 11) { + // Activation has been removed in JDK 17. + rci.initializeAtBuildTime("sun.rmi.server.Activation$ActivationSystemImpl_Stub", "JDK11 JMX support"); + } + rci.initializeAtBuildTime("jdk.management.jfr.SettingDescriptorInfo", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log$LogStreamLog", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log", "JMX support"); + rci.initializeAtBuildTime("java.rmi.server.LogStream", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log$LoggerLog", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.server.Util", "JMX support"); + rci.initializeAtBuildTime("jdk.management.jfr.MBeanUtils", "JMX support"); + + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.StandardMBeanIntrospector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanLookup", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp", "JMX support"); + rci.initializeAtBuildTime("java.rmi.server.RemoteObjectInvocationHandler", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector", "JMX support"); + rci.initializeAtBuildTime("java.beans.Introspector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.JavaBeansAccessor", "JMX support"); + + rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MBeanInstantiator", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ArrayNotificationBuffer", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.security.HashedPasswordManager", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXSubjectDomainCombiner", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerCommunicatorAdmin", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.defaults.JmxProperties", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerNotifForwarder", "JMX support"); + + rci.initializeAtRunTime("sun.rmi.transport.ConnectionInputStream", "JMX support"); + rci.initializeAtRunTime("java.rmi.MarshalledObject$MarshalledObjectInputStream", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastRef2", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastRef", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.MarshalInputStream", "JMX support"); + rci.initializeAtRunTime("sun.rmi.runtime.NewThreadAction", "JMX support"); + rci.initializeAtRunTime("com.sun.jmx.remote.security.FileLoginModule", "JMX support"); + rci.initializeAtRunTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator$FileLoginConfig", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCImpl", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCAckHandler", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.GC", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCClient", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.ObjectTable", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPEndpoint", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPChannel", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPTransport", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.Transport", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.ObjID", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.UID", "JMX support"); + rci.initializeAtRunTime("sun.rmi.runtime.RuntimeUtil", "JMX support"); + rci.initializeAtRunTime("java.rmi.dgc.VMID", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.RMIClassLoader", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.LoaderHandler", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.RemoteServer", "JMX support"); + rci.initializeAtRunTime("sun.rmi.registry.RegistryImpl", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.UnicastRemoteObject", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef2", "JMX support"); + } + + private static void handleNativeLibraries(BeforeAnalysisAccess access) { + + // This is required for password authentication. + // JMX checks the restrictions on the password file via a JNI native method. + NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("management_agent"); + BeforeAnalysisAccessImpl beforeAnalysisAccess = (BeforeAnalysisAccessImpl) access; + beforeAnalysisAccess.getNativeLibraries().addStaticJniLibrary("management_agent"); + // Resolve calls to jdk_internal_agent* as builtIn. For calls to native method + // isAccessUserOnly0. + PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("jdk_internal_agent"); + } + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + handleNativeLibraries(access); + registerJMXAgentResources(); + configureJNI(); + configureSerialization(access); + configureReflection(access); + configureProxy(access); + RuntimeSupport.getRuntimeSupport().addStartupHook(new ManagementAgentStartupHook()); + } + + private static void registerJMXAgentResources() { + ResourcesRegistry resourcesRegistry = ImageSingletons.lookup(ResourcesRegistry.class); + + resourcesRegistry.addResourceBundles(ConfigurationCondition.alwaysTrue(), + "jdk.internal.agent.resources.agent"); + + resourcesRegistry.addResourceBundles(ConfigurationCondition.alwaysTrue(), + "sun.security.util.Resources"); // required for password auth + } + + private static void configureProxy(BeforeAnalysisAccess access) { + DynamicProxyRegistry dynamicProxySupport = ImageSingletons.lookup(DynamicProxyRegistry.class); + + dynamicProxySupport.addProxyClass(access.findClassByName("java.rmi.Remote"), + access.findClassByName("java.rmi.registry.Registry")); + + dynamicProxySupport.addProxyClass(access.findClassByName("javax.management.remote.rmi.RMIServer")); + + dynamicProxySupport.addProxyClass(access.findClassByName("jdk.management.jfr.FlightRecorderMXBean"), + access.findClassByName("javax.management.NotificationEmitter")); + + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.RuntimeMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ClassLoadingMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryManagerMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.BufferPoolMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryPoolMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.UnixOperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.java.lang.management.CompilationMXBean")); + } + + private static void configureJNI() { + JNIRuntimeAccess.register(Arrays.class); + JNIRuntimeAccess.register(ReflectionUtil.lookupMethod(Arrays.class, "asList", Object[].class)); + } + + private static void configureSerialization(BeforeAnalysisAccess access) { + String[] classes = new String[]{ + "[B", "com.oracle.svm.core.jdk.UnsupportedFeatureError", + "java.io.IOException", "java.lang.Boolean", "java.lang.ClassCastException", "java.lang.Error", + "java.lang.Exception", "java.lang.IllegalArgumentException", "java.lang.IllegalStateException", + "java.lang.Integer", "[Ljava.lang.Integer;", "java.lang.Long", "java.lang.NoSuchMethodException", + "java.lang.Number", "[Ljava.lang.Object;", "java.lang.ReflectiveOperationException", + "java.lang.RuntimeException", "java.lang.SecurityException", "java.lang.StackTraceElement", + "[Ljava.lang.StackTraceElement;", "java.lang.String", "java.lang.Throwable", + "java.lang.UnsupportedOperationException", + "java.rmi.MarshalledObject", "[Ljava.rmi.MarshalledObject;", "java.rmi.RemoteException", + "java.rmi.ServerError", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", "java.rmi.server.ObjID", + "[Ljava.rmi.server.ObjID;", "java.rmi.server.RemoteObject", "java.rmi.server.RemoteStub", + "java.rmi.server.UID", "java.security.GeneralSecurityException", "java.util.ArrayList", + "java.util.Arrays$ArrayList", "java.util.Collections$EmptyList", + "java.util.Collections$UnmodifiableCollection", "java.util.Collections$UnmodifiableList", + "java.util.Collections$UnmodifiableRandomAccessList", + "java.util.EventObject", // Required for notifications + "java.util.HashMap", "java.util.HashSet", + "java.util.LinkedHashMap", "java.util.MissingResourceException", "java.util.TreeMap", + "java.util.Vector", "javax.management.Attribute", "javax.management.AttributeList", + "javax.management.AttributeNotFoundException", + "javax.management.AttributeChangeNotification", // Required for + // notifications + "javax.management.InstanceNotFoundException", + "javax.management.JMException", "javax.management.MBeanAttributeInfo", + "[Ljavax.management.MBeanAttributeInfo;", "[Ljavax.management.MBeanConstructorInfo;", + "javax.management.MBeanFeatureInfo", "javax.management.MBeanInfo", + "javax.management.MBeanNotificationInfo", "[Ljavax.management.MBeanNotificationInfo;", + "javax.management.MBeanOperationInfo", "[Ljavax.management.MBeanOperationInfo;", + "javax.management.MBeanParameterInfo", "[Ljavax.management.MBeanParameterInfo;", + "javax.management.Notification", // Required for notifications + "javax.management.NotificationFilterSupport", "javax.management.ObjectName", + "[Ljavax.management.ObjectName;", "javax.management.OperationsException", "javax.management.ReflectionException", + "javax.management.openmbean.ArrayType", "javax.management.openmbean.CompositeDataSupport", + "[Ljavax.management.openmbean.CompositeData;", "javax.management.openmbean.CompositeType", + "javax.management.openmbean.OpenMBeanAttributeInfoSupport", + "javax.management.openmbean.OpenMBeanParameterInfoSupport", "javax.management.openmbean.OpenType", + "javax.management.openmbean.SimpleType", "javax.management.openmbean.TabularDataSupport", + "javax.management.openmbean.TabularType", "javax.management.remote.NotificationResult", + "javax.management.remote.TargetedNotification", // Required for + // notifications + "[Ljavax.management.remote.TargetedNotification;", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServerImpl_Stub", "javax.management.RuntimeMBeanException", + "javax.rmi.ssl.SslRMIClientSocketFactory", // Required for SSL + "[Ljavax.security.auth.Subject;", "javax.security.auth.login.FailedLoginException", + "javax.security.auth.login.LoginException", "[J", "java.rmi.NoSuchObjectException", + "javax.management.JMRuntimeException", "javax.management.RuntimeErrorException" + }; + + for (String clazz : classes) { + RuntimeSerialization.register(access.findClassByName(clazz)); + } + } + + private static void configureReflection(BeforeAnalysisAccess access) { + /* + * Register all the custom substrate MXBeans. They won't be accounted for by the native + * image tracing agent so a user may not know they need to register them. + */ + Set platformManagedObjects = com.oracle.svm.core.jdk.management.ManagementSupport + .getSingleton().getPlatformManagedObjects(); + for (PlatformManagedObject p : platformManagedObjects) { // TODO: maybe its better to + // hardcode these because + // platform mbeans are lazily + // init at runtime + Class clazz = p.getClass(); + RuntimeReflection.register(clazz); + RuntimeReflection.register(clazz.getDeclaredConstructors()); + RuntimeReflection.register(clazz.getDeclaredMethods()); + RuntimeReflection.register(clazz.getDeclaredFields()); + RuntimeReflection.register(clazz.getInterfaces()); + } + + // Only JmxServerFeature, not JmxClientFeature, has registrations for platform MBeans + String[] classes = new String[]{ + "com.sun.crypto.provider.AESCipher$General", "com.sun.crypto.provider.ARCFOURCipher", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", "com.sun.crypto.provider.DESCipher", + "com.sun.crypto.provider.DESedeCipher", "com.sun.crypto.provider.DHParameters", + "com.sun.crypto.provider.HmacCore$HmacSHA256", "com.sun.management.GarbageCollectorMXBean", + "com.sun.management.GcInfo", "com.sun.management.OperatingSystemMXBean", + "com.sun.management.internal.OperatingSystemImpl", "com.sun.management.ThreadMXBean", + "com.sun.management.UnixOperatingSystemMXBean", "java.lang.management.CompilationMXBean", + "java.lang.management.GarbageCollectorMXBean", "java.lang.management.MemoryMXBean", + "java.lang.management.MemoryManagerMXBean", "java.lang.management.MemoryPoolMXBean", + "java.lang.management.RuntimeMXBean", "java.lang.management.BufferPoolMXBean", + "java.lang.management.ClassLoadingMXBean", "java.lang.management.PlatformLoggingMXBean", + "javax.management.remote.rmi.RMIConnection", "com.sun.management.VMOption", + "javax.management.remote.rmi.RMIConnectionImpl_Stub", "javax.management.remote.rmi.RMIServer", + "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.registry.RegistryImpl_Stub", + "java.rmi.MarshalledObject", "java.rmi.Remote", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", + "java.rmi.registry.Registry", "java.rmi.server.ObjID", "java.rmi.server.RemoteObject", + "java.rmi.server.RemoteStub", "java.rmi.server.UID", "javax.management.openmbean.OpenType", + "java.lang.management.LockInfo", "java.lang.management.ManagementPermission", + "java.lang.management.MemoryUsage", "java.lang.management.MonitorInfo", + "java.lang.management.ThreadInfo", "java.security.SecureRandomParameters", + "javax.management.MBeanServerBuilder", "javax.management.NotificationBroadcaster", + "javax.management.NotificationEmitter", "javax.management.NotificationFilterSupport", + "javax.management.ObjectName", "jdk.management.jfr.ConfigurationInfo", + "jdk.management.jfr.EventTypeInfo", "jdk.management.jfr.FlightRecorderMXBean", + "jdk.management.jfr.RecordingInfo", "jdk.management.jfr.SettingDescriptorInfo", + "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.transport.DGCImpl_Skel", + "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", + "sun.rmi.transport.DGCImpl_Stub" + }; + + String[] methods = new String[]{ + "com.sun.management.GcInfo", "com.sun.management.OperatingSystemMXBean", + "com.sun.management.ThreadMXBean", "com.sun.management.UnixOperatingSystemMXBean", + "com.sun.management.VMOption", "java.lang.management.BufferPoolMXBean", + "java.lang.management.ClassLoadingMXBean", "java.lang.management.CompilationMXBean", + "java.lang.management.GarbageCollectorMXBean", "java.lang.management.MemoryMXBean", + "java.lang.management.MemoryManagerMXBean", "java.lang.management.MemoryPoolMXBean", + "java.lang.management.MemoryUsage", "java.lang.management.RuntimeMXBean", + "java.lang.management.PlatformLoggingMXBean", "java.rmi.registry.Registry", + "javax.management.remote.rmi.RMIConnection", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServer", "javax.management.remote.rmi.RMIServerImpl_Stub", + "jdk.management.jfr.FlightRecorderMXBean", "java.lang.management.MonitorInfo", + "java.lang.management.ThreadInfo", "jdk.management.jfr.ConfigurationInfo", + "jdk.management.jfr.EventTypeInfo", "jdk.management.jfr.RecordingInfo", + "jdk.management.jfr.SettingDescriptorInfo", "sun.rmi.registry.RegistryImpl_Stub", + "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", + "sun.rmi.transport.DGCImpl_Stub" + }; + + String[] fields = new String[]{"com.sun.management.GcInfo"}; + + String[] constructors = new String[]{ + "com.sun.management.internal.GarbageCollectorExtImpl", + "com.sun.management.internal.OperatingSystemImpl", "java.lang.management.ManagementPermission", + "javax.management.MBeanServerBuilder", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.transport.DGCImpl_Stub", + "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.registry.RegistryImpl_Stub", + "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl_Skel" + }; + + for (String clazz : classes) { + RuntimeReflection.register(access.findClassByName(clazz)); + } + for (String clazz : methods) { + RuntimeReflection.register(access.findClassByName(clazz).getMethods()); + } + for (String clazz : constructors) { + RuntimeReflection.register(access.findClassByName(clazz).getConstructors()); + } + for (String clazz : fields) { + RuntimeReflection.register(access.findClassByName(clazz).getFields()); + } + } +} diff --git a/substratevm/src/com.oracle.svm.test/src/META-INF/native-image/com.oracle.svm.test/native-image.properties b/substratevm/src/com.oracle.svm.test/src/META-INF/native-image/com.oracle.svm.test/native-image.properties index 37f5294dfb4a..73b4b44b9f04 100644 --- a/substratevm/src/com.oracle.svm.test/src/META-INF/native-image/com.oracle.svm.test/native-image.properties +++ b/substratevm/src/com.oracle.svm.test/src/META-INF/native-image/com.oracle.svm.test/native-image.properties @@ -8,4 +8,4 @@ Args= \ --features=com.oracle.svm.test.jfr.JfrTestFeature \ --add-opens=java.base/java.lang=ALL-UNNAMED \ --add-exports=org.graalvm.nativeimage.base/com.oracle.svm.util=ALL-UNNAMED \ - --enable-monitoring=jfr \ No newline at end of file + --enable-monitoring=jfr,jmxserver,jmxclient \ No newline at end of file diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/JmxTest.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/JmxTest.java new file mode 100644 index 000000000000..e8e6653e89f6 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/JmxTest.java @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.test.jmx; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import java.io.IOException; +import java.lang.management.ClassLoadingMXBean; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.lang.management.ThreadMXBean; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryManagerMXBean; +import java.lang.management.OperatingSystemMXBean; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.BufferPoolMXBean; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryUsage; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.management.jfr.FlightRecorderMXBean; +import org.graalvm.nativeimage.ImageInfo; +import org.junit.BeforeClass; +import org.junit.Test; +import com.oracle.svm.test.AddExports; +import com.oracle.svm.core.jdk.management.ManagementAgentStartupHook; +import com.oracle.svm.core.VMInspectionOptions; + +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import org.junit.Assert; + +@AddExports("jdk.management.agent/jdk.internal.agent") +public class JmxTest { + static final String PORT_PROPERTY = "com.sun.management.jmxremote.port"; + static final String AUTH_PROPERTY = "com.sun.management.jmxremote.authenticate"; + static final String SSL_PROPERTY = "com.sun.management.jmxremote.ssl"; + static final String TEST_PORT = "12345"; + static final String FALSE = "false"; + + @BeforeClass + public static void checkForJFR() { + assumeTrue("skipping JMX tests", !ImageInfo.inImageCode() || + (VMInspectionOptions.hasJmxClientSupport() && VMInspectionOptions.hasJmxServerSupport())); + + System.setProperty(PORT_PROPERTY, TEST_PORT); + System.setProperty(AUTH_PROPERTY, FALSE); + System.setProperty(SSL_PROPERTY, FALSE); + try { + // We need to rerun the startup hook with the correct properties set. + ManagementAgentStartupHook startupHook = new ManagementAgentStartupHook(); + startupHook.execute(false); + } catch (Exception e) { + Assert.fail("Failed to start server Cause: " + e.getMessage()); + } + } + + private static MBeanServerConnection getLocalMBeanServerConnectionStatic() { + try { + JMXServiceURL jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + "localhost" + ":" + TEST_PORT + "/jmxrmi"); + Map env = new HashMap<>(); + + JMXConnector connector = JMXConnectorFactory.connect(jmxUrl, env); + return connector.getMBeanServerConnection(); + } catch (IOException e) { + Assert.fail("Failed to establish connection Cause: " + e.getMessage()); + } + return null; + } + + @Test + public void testConnection() throws Exception { + // This simply tests that we can establish a connection between client and server + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + assertTrue("Connection should not be null", mbsc != null); + assertTrue("Connection default domain should not be empty", !mbsc.getDefaultDomain().isEmpty()); + } + + @Test + public void testRegistration() throws Exception { + // This tests whether we can register a bean with the server locally and access it remotely + // from the client via the connection + ObjectName objectName = new ObjectName("com.jmx.test.basic:type=basic,name=simple"); + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + try { + server.getDefaultDomain(); + server.registerMBean(new Simple(), objectName); + + } catch (Exception e) { + Assert.fail("Failed to register bean. Cause: " + e.getMessage()); + } + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + assertTrue("Expected bean is not registered.", mbsc.isRegistered(objectName)); + + } + + @Test + public void testRuntimeMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + RuntimeMXBean runtimeMXBean = null; + try { + runtimeMXBean = ManagementFactory.getPlatformMXBean(mbsc, RuntimeMXBean.class); + } catch (IOException e) { + Assert.fail("Failed to get RuntimeMXBean. : " + e.getMessage()); + } + assertTrue("Uptime should be positive. ", runtimeMXBean.getUptime() > 0); + assertTrue("PID should be positive.", runtimeMXBean.getPid() > 0); + assertTrue("Class Path should not be null: ", runtimeMXBean.getClassPath() != null); + assertTrue("Start time should be positive", runtimeMXBean.getStartTime() > 0); + } + + @Test + public void testClassLoadingMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + + ClassLoadingMXBean classLoadingMXBean = null; + try { + classLoadingMXBean = ManagementFactory.getPlatformMXBean(mbsc, ClassLoadingMXBean.class); + } catch (IOException e) { + Assert.fail("Failed to get ClassLoadingMXBean. : " + e.getMessage()); + } + if (ImageInfo.inImageRuntimeCode()) { + assertTrue("Loaded Class count should be 0 (hardcoded at 0): ", classLoadingMXBean.getLoadedClassCount() == 0); + } else { + assertTrue("If in java mode, number of loaded classes should be positive: ", classLoadingMXBean.getLoadedClassCount() > 0); + } + } + + @Test + public void testThreadMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + ThreadMXBean threadMXBean = null; + try { + threadMXBean = ManagementFactory.getPlatformMXBean(mbsc, ThreadMXBean.class); + } catch (IOException e) { + Assert.fail("Failed to get ThreadMXBean. : " + e.getMessage()); + } + int count = threadMXBean.getPeakThreadCount(); + assertTrue("Peak thread count should be positive ", count > 0); + threadMXBean.resetPeakThreadCount(); + assertTrue("Peak thread count should be positive.", threadMXBean.getPeakThreadCount() > 0); + if (!ImageInfo.inImageRuntimeCode()) { + assertTrue("Current thread user time should be positive in java mode", threadMXBean.getCurrentThreadUserTime() >= 0); + } + + } + + @Test + public void testMemoryMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + MemoryMXBean memoryMXBean = null; + try { + memoryMXBean = ManagementFactory.getPlatformMXBean(mbsc, MemoryMXBean.class); + + } catch (Exception e) { + Assert.fail("Failed to get MemoryMXBean. : " + e.getMessage()); + } + MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage(); + assertTrue("Memory usage should be positive: ", memoryUsage.getUsed() > 0); + + } + + @Test + public void testGarbageCollectorMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + List garbageCollectorMXBeans = null; + try { + garbageCollectorMXBeans = ManagementFactory.getPlatformMXBeans(mbsc, GarbageCollectorMXBean.class); + + } catch (Exception e) { + Assert.fail("Failed to get GarbageCollectorMXBean. : " + e.getMessage()); + } + for (GarbageCollectorMXBean gcBean : garbageCollectorMXBeans) { + assertTrue("GC object name should not be null", gcBean.getObjectName() != null); + assertTrue("Number of GC should not be negative", gcBean.getCollectionCount() >= 0); + } + } + + @Test + public void testOperatingSystemMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + + OperatingSystemMXBean operatingSystemMXBean = null; + try { + operatingSystemMXBean = ManagementFactory.getPlatformMXBean(mbsc, OperatingSystemMXBean.class); + + } catch (Exception e) { + Assert.fail("Failed to get OperatingSystemMXBean. : " + e.getMessage()); + } + assertTrue("OS version can't be null. ", operatingSystemMXBean.getVersion() != null); + } + + @Test + public void testMemoryManagerMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + List memoryManagerMXBeans = null; + try { + memoryManagerMXBeans = ManagementFactory.getPlatformMXBeans(mbsc, MemoryManagerMXBean.class); + + } catch (Exception e) { + Assert.fail("Failed to get MemoryManagerMXBean. : " + e.getMessage()); + } + for (MemoryManagerMXBean memoryManagerMXBean : memoryManagerMXBeans) { + assertTrue("Memory pool names should not be null. ", memoryManagerMXBean.getMemoryPoolNames() != null); + } + } + + @Test + public void testBufferPoolMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + List bufferPoolMXBeans = null; + try { + bufferPoolMXBeans = ManagementFactory.getPlatformMXBeans(mbsc, BufferPoolMXBean.class); + + } catch (Exception e) { + Assert.fail("Failed to get BufferPoolMXBean. : " + e.getMessage()); + } + for (BufferPoolMXBean bufferPoolMXBean : bufferPoolMXBeans) { + assertTrue("Total buffer pool capacity should be positive. ", bufferPoolMXBean.getName() != null); + } + } + + @Test + public void testMemoryPoolMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + + List memoryPoolMXBeans = null; + try { + memoryPoolMXBeans = ManagementFactory.getPlatformMXBeans(mbsc, MemoryPoolMXBean.class); + + } catch (Exception e) { + Assert.fail("Failed to get MemoryPoolMXBean. : " + e.getMessage()); + } + for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeans) { + assertTrue("Memory Pool name should not be null ", memoryPoolMXBean.getName() != null); + } + } + + @Test + public void testFlightRecorderMXBean() { + // This test checks to make sure we are able to get the MXBean and do simple things with it. + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + + FlightRecorderMXBean flightRecorderMXBean = null; + try { + flightRecorderMXBean = ManagementFactory.getPlatformMXBean(mbsc, FlightRecorderMXBean.class); + + } catch (Exception e) { + Assert.fail("Failed to get FlightRecorderMXBean. : " + e.getMessage()); + } + flightRecorderMXBean.newRecording(); + assertTrue("Flight recordings should be available because we just created one.", !flightRecorderMXBean.getRecordings().isEmpty()); + } + + @Test + public void testRemoteInvocation() throws MalformedObjectNameException { + MBeanServerConnection mbsc = getLocalMBeanServerConnectionStatic(); + ObjectName objectName = new ObjectName("jdk.management.jfr:type=FlightRecorder"); + try { + long recording = (long) mbsc.invoke(objectName, "newRecording", null, null); + mbsc.invoke(objectName, "startRecording", new Object[]{recording}, new String[]{"long"}); + mbsc.invoke(objectName, "stopRecording", new Object[]{recording}, new String[]{"long"}); + } catch (Exception e) { + Assert.fail("Remote invokations failed : " + e.getMessage()); + } + } +} diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/Simple.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/Simple.java new file mode 100644 index 000000000000..635efc460e0d --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/Simple.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.test.jmx; + +public class Simple implements SimpleMBean { + + private String name = ""; + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + +} diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/SimpleMBean.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/SimpleMBean.java new file mode 100644 index 000000000000..7e2d2213a066 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jmx/SimpleMBean.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.test.jmx; + +public interface SimpleMBean { + String getName(); + + void setName(String name); + +} From 23684af9516d1f92c53f163d67c926127f08dbf6 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 2 Dec 2022 15:46:20 +0100 Subject: [PATCH 2/6] Set monitoring features explicitly for launchers. --- sdk/mx.sdk/mx_sdk_vm_impl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py index b3eaec53cb8e..2964d8607ccf 100644 --- a/sdk/mx.sdk/mx_sdk_vm_impl.py +++ b/sdk/mx.sdk/mx_sdk_vm_impl.py @@ -1271,7 +1271,7 @@ def contents(self): if isinstance(image_config, mx_sdk.LauncherConfig) or (isinstance(image_config, mx_sdk.LanguageLibraryConfig) and image_config.launchers): build_args += [ '--install-exit-handlers', - '--enable-monitoring', + '--enable-monitoring=jvmstat,heapdump,jfr', '-H:+DumpRuntimeCompilationOnSignal', ] From 04281d8fc4e35636a7b21954872ca44aa89722d8 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 12 Dec 2022 13:05:10 -0500 Subject: [PATCH 3/6] factor out common code into third feature --- .../svm/hosted/jdk/JmxClientFeature.java | 223 +-------------- .../svm/hosted/jdk/JmxCommonFeature.java | 266 ++++++++++++++++++ .../svm/hosted/jdk/JmxServerFeature.java | 208 +------------- 3 files changed, 279 insertions(+), 418 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java index f0c07815b6b2..3889021e42b8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java @@ -25,9 +25,6 @@ */ package com.oracle.svm.hosted.jdk; -import java.util.Arrays; - -import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.feature.InternalFeature; import org.graalvm.nativeimage.hosted.RuntimeReflection; @@ -37,9 +34,7 @@ import com.oracle.svm.core.jdk.NativeLibrarySupport; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; -import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; import com.oracle.svm.core.jni.JNIRuntimeAccess; -import org.graalvm.nativeimage.hosted.RuntimeSerialization; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.VMInspectionOptions; import com.oracle.svm.util.ReflectionUtil; @@ -51,70 +46,6 @@ public boolean isInConfiguration(IsInConfigurationAccess access) { return VMInspectionOptions.hasJmxClientSupport(); } - @Override - public void afterRegistration(AfterRegistrationAccess access) { - org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport rci = ImageSingletons.lookup(org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport.class); - if (org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC <= 11) { - // Activation has been removed in JDK 17. - rci.initializeAtBuildTime("sun.rmi.server.Activation$ActivationSystemImpl_Stub", "JDK11 JMX support"); - } - - rci.initializeAtBuildTime("jdk.management.jfr.SettingDescriptorInfo", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.runtime.Log$LogStreamLog", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.runtime.Log", "JMX support"); - rci.initializeAtBuildTime("java.rmi.server.LogStream", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.runtime.Log$LoggerLog", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.server.Util", "JMX support"); - rci.initializeAtBuildTime("jdk.management.jfr.MBeanUtils", "JMX support"); - - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.StandardMBeanIntrospector", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanLookup", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp", "JMX support"); - rci.initializeAtBuildTime("java.rmi.server.RemoteObjectInvocationHandler", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector", "JMX support"); - rci.initializeAtBuildTime("java.beans.Introspector", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.JavaBeansAccessor", "JMX support"); - - rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MBeanInstantiator", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ArrayNotificationBuffer", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.security.HashedPasswordManager", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXSubjectDomainCombiner", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerCommunicatorAdmin", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.defaults.JmxProperties", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerNotifForwarder", "JMX support"); - - rci.initializeAtRunTime("sun.rmi.transport.ConnectionInputStream", "JMX support"); - rci.initializeAtRunTime("java.rmi.MarshalledObject$MarshalledObjectInputStream", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastRef2", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastRef", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.MarshalInputStream", "JMX support"); - rci.initializeAtRunTime("sun.rmi.runtime.NewThreadAction", "JMX support"); - rci.initializeAtRunTime("com.sun.jmx.remote.security.FileLoginModule", "JMX support"); - rci.initializeAtRunTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator$FileLoginConfig", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.DGCImpl", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.DGCAckHandler", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.GC", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.DGCClient", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.ObjectTable", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPEndpoint", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPChannel", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPTransport", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.Transport", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.ObjID", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.UID", "JMX support"); - rci.initializeAtRunTime("sun.rmi.runtime.RuntimeUtil", "JMX support"); - rci.initializeAtRunTime("java.rmi.dgc.VMID", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.RMIClassLoader", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.LoaderHandler", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.RemoteServer", "JMX support"); - rci.initializeAtRunTime("sun.rmi.registry.RegistryImpl", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.UnicastRemoteObject", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef2", "JMX support"); - } - private static void handleNativeLibraries(BeforeAnalysisAccess access) { BeforeAnalysisAccessImpl a = (BeforeAnalysisAccessImpl) access; NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("rmi"); @@ -128,9 +59,7 @@ private static void handleNativeLibraries(BeforeAnalysisAccess access) { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { try { - configureProxy(access); configureJNI(); - configureSerialization(access); configureReflection(access); handleNativeLibraries(access); } catch (Exception e) { @@ -138,160 +67,18 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { } } - private static void configureProxy(BeforeAnalysisAccess access) { - DynamicProxyRegistry dynamicProxySupport = ImageSingletons.lookup(DynamicProxyRegistry.class); - - dynamicProxySupport.addProxyClass(access.findClassByName("jdk.management.jfr.FlightRecorderMXBean"), - access.findClassByName("javax.management.NotificationEmitter")); - - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.RuntimeMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ClassLoadingMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.ThreadMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ThreadMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.OperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.OperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryManagerMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.BufferPoolMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryPoolMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.UnixOperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.java.lang.management.CompilationMXBean")); - } - private static void configureJNI() { - JNIRuntimeAccess.register(Arrays.class); - JNIRuntimeAccess.register(ReflectionUtil.lookupMethod(Arrays.class, "asList", Object[].class)); JNIRuntimeAccess.register(Boolean.class); JNIRuntimeAccess.register(ReflectionUtil.lookupMethod(Boolean.class, "getBoolean", String.class)); } - // seems like the serialization is the same for both client and server, maybe we - // can reduce code duplication. - private static void configureSerialization(BeforeAnalysisAccess access) { - String[] classes = new String[]{ - "[B", "com.oracle.svm.core.jdk.UnsupportedFeatureError", - "java.io.IOException", "java.lang.Boolean", "java.lang.ClassCastException", "java.lang.Error", - "java.lang.Exception", "java.lang.IllegalArgumentException", "java.lang.IllegalStateException", - "java.lang.Integer", "[Ljava.lang.Integer;", "java.lang.Long", "java.lang.NoSuchMethodException", - "java.lang.Number", "[Ljava.lang.Object;", "java.lang.ReflectiveOperationException", - "java.lang.RuntimeException", "java.lang.SecurityException", "java.lang.StackTraceElement", - "[Ljava.lang.StackTraceElement;", "java.lang.String", "java.lang.Throwable", - "java.lang.UnsupportedOperationException", - "java.rmi.MarshalledObject", "[Ljava.rmi.MarshalledObject;", "java.rmi.RemoteException", - "java.rmi.ServerError", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", "java.rmi.server.ObjID", - "[Ljava.rmi.server.ObjID;", "java.rmi.server.RemoteObject", "java.rmi.server.RemoteStub", - "java.rmi.server.UID", "java.security.GeneralSecurityException", "java.util.ArrayList", - "java.util.Arrays$ArrayList", "java.util.Collections$EmptyList", - "java.util.Collections$UnmodifiableCollection", "java.util.Collections$UnmodifiableList", - "java.util.Collections$UnmodifiableRandomAccessList", - "java.util.EventObject", // Required for notifications - "java.util.HashMap", "java.util.HashSet", - "java.util.LinkedHashMap", "java.util.MissingResourceException", "java.util.TreeMap", - "java.util.Vector", "javax.management.Attribute", "javax.management.AttributeList", - "javax.management.AttributeNotFoundException", - "javax.management.AttributeChangeNotification", // Required for - // notifications - "javax.management.InstanceNotFoundException", - "javax.management.JMException", "javax.management.MBeanAttributeInfo", - "[Ljavax.management.MBeanAttributeInfo;", "[Ljavax.management.MBeanConstructorInfo;", - "javax.management.MBeanFeatureInfo", "javax.management.MBeanInfo", - "javax.management.MBeanNotificationInfo", "[Ljavax.management.MBeanNotificationInfo;", - "javax.management.MBeanOperationInfo", "[Ljavax.management.MBeanOperationInfo;", - "javax.management.MBeanParameterInfo", "[Ljavax.management.MBeanParameterInfo;", - "javax.management.Notification", // Required for notifications - "javax.management.NotificationFilterSupport", "javax.management.ObjectName", - "[Ljavax.management.ObjectName;", "javax.management.OperationsException", "javax.management.ReflectionException", - "javax.management.openmbean.ArrayType", "javax.management.openmbean.CompositeDataSupport", - "[Ljavax.management.openmbean.CompositeData;", "javax.management.openmbean.CompositeType", - "javax.management.openmbean.OpenMBeanAttributeInfoSupport", - "javax.management.openmbean.OpenMBeanParameterInfoSupport", "javax.management.openmbean.OpenType", - "javax.management.openmbean.SimpleType", "javax.management.openmbean.TabularDataSupport", - "javax.management.openmbean.TabularType", "javax.management.remote.NotificationResult", - "javax.management.remote.TargetedNotification", // Required for - // notifications - "[Ljavax.management.remote.TargetedNotification;", "javax.management.remote.rmi.RMIConnectionImpl_Stub", - "javax.management.remote.rmi.RMIServerImpl_Stub", "javax.management.RuntimeMBeanException", - "javax.rmi.ssl.SslRMIClientSocketFactory", // Required for SSL - "[Ljavax.security.auth.Subject;", "javax.security.auth.login.FailedLoginException", - "javax.security.auth.login.LoginException", "[J", "java.rmi.NoSuchObjectException", - "javax.management.JMRuntimeException", "javax.management.RuntimeErrorException" - }; - - for (String clazz : classes) { - RuntimeSerialization.register(access.findClassByName(clazz)); - } - } - private static void configureReflection(BeforeAnalysisAccess access) { - String[] classes = new String[]{ - "com.sun.crypto.provider.AESCipher$General", - "com.sun.crypto.provider.ARCFOURCipher", "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", - "com.sun.crypto.provider.DESCipher", "com.sun.crypto.provider.DESedeCipher", - "com.sun.crypto.provider.DHParameters", - "com.sun.crypto.provider.HmacCore$HmacSHA256", - "com.sun.jndi.url.rmi.rmiURLContextFactory", // Unique to client - "com.sun.management.GcInfo", "com.sun.management.VMOption", - "com.sun.management.internal.OperatingSystemImpl", "java.rmi.MarshalledObject", "java.rmi.Remote", - "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", "java.rmi.registry.Registry", "java.rmi.server.ObjID", - "java.rmi.server.RemoteObject", "java.rmi.server.RemoteStub", "java.rmi.server.UID", - "java.lang.management.LockInfo", "java.lang.management.ManagementPermission", - "java.lang.management.MemoryUsage", "java.lang.management.MonitorInfo", - "java.lang.management.ThreadInfo", "java.security.SecureRandomParameters", - "javax.management.MBeanServerBuilder", "javax.management.NotificationBroadcaster", - "javax.management.NotificationEmitter", "javax.management.NotificationFilterSupport", - "javax.management.ObjectName", "javax.management.openmbean.OpenType", - "javax.management.remote.rmi.RMIConnection", "javax.management.remote.rmi.RMIConnectionImpl_Stub", - "javax.management.remote.rmi.RMIServer", "javax.management.remote.rmi.RMIServerImpl_Stub", - "jdk.management.jfr.FlightRecorderMXBean", "jdk.management.jfr.ConfigurationInfo", - "jdk.management.jfr.EventTypeInfo", "jdk.management.jfr.RecordingInfo", - "jdk.management.jfr.SettingDescriptorInfo", "sun.rmi.registry.RegistryImpl_Skel", - "sun.rmi.registry.RegistryImpl_Stub", "sun.rmi.server.UnicastRef2", - "sun.rmi.server.UnicastRef", // Unique to client - "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", "sun.rmi.transport.DGCImpl_Skel", - "sun.rmi.transport.DGCImpl_Stub" - }; - - String[] methods = new String[]{ - "com.sun.management.GcInfo", "com.sun.management.VMOption", - "java.rmi.registry.Registry", "jdk.management.jfr.FlightRecorderMXBean", - "java.lang.management.MemoryUsage", "java.lang.management.MonitorInfo", - "java.lang.management.ThreadInfo", "javax.management.remote.rmi.RMIConnectionImpl_Stub", - "javax.management.remote.rmi.RMIServer", "javax.management.remote.rmi.RMIServerImpl_Stub", - "javax.management.remote.rmi.RMIConnection", "javax.management.remote.rmi.RMIConnection", - "jdk.management.jfr.ConfigurationInfo", "jdk.management.jfr.EventTypeInfo", - "jdk.management.jfr.RecordingInfo", "jdk.management.jfr.SettingDescriptorInfo", - "sun.rmi.registry.RegistryImpl_Stub", "sun.rmi.server.UnicastRef2", "sun.rmi.server.UnicastRef", - "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", "sun.rmi.transport.DGCImpl_Stub" - }; + RuntimeReflection.register(access.findClassByName("com.sun.jndi.url.rmi.rmiURLContextFactory")); + RuntimeReflection.register(access.findClassByName("sun.rmi.server.UnicastRef")); - String[] fields = new String[]{"com.sun.management.GcInfo"}; + RuntimeReflection.register(access.findClassByName("sun.rmi.server.UnicastRef").getMethods()); - String[] constructors = new String[]{"com.sun.jndi.url.rmi.rmiURLContextFactory", - "com.sun.management.internal.GarbageCollectorExtImpl", - "com.sun.management.internal.OperatingSystemImpl", "java.lang.management.ManagementPermission", - "javax.management.MBeanServerBuilder", "javax.management.remote.rmi.RMIConnectionImpl_Stub", - "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.transport.DGCImpl_Stub", - "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.registry.RegistryImpl_Stub", - "sun.rmi.server.UnicastRef2", "sun.rmi.server.UnicastRef", "sun.rmi.transport.DGCImpl_Skel" - }; - - for (String clazz : classes) { - Class c = access.findClassByName(clazz); - if (c == null) { - continue; - } - RuntimeReflection.register(c); - } - for (String clazz : methods) { - RuntimeReflection.register(access.findClassByName(clazz).getMethods()); - } - for (String clazz : constructors) { - RuntimeReflection.register(access.findClassByName(clazz).getConstructors()); - } - for (String clazz : fields) { - RuntimeReflection.register(access.findClassByName(clazz).getFields()); - } + RuntimeReflection.register(access.findClassByName("com.sun.jndi.url.rmi.rmiURLContextFactory").getConstructors()); + RuntimeReflection.register(access.findClassByName("sun.rmi.server.UnicastRef").getConstructors()); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java new file mode 100644 index 000000000000..ae90869d1c3d --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.hosted.jdk; + +import java.util.Arrays; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.RuntimeReflection; +import org.graalvm.nativeimage.hosted.RuntimeSerialization; +import com.oracle.svm.core.VMInspectionOptions; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; +import com.oracle.svm.core.jni.JNIRuntimeAccess; +import com.oracle.svm.util.ReflectionUtil; + +@AutomaticallyRegisteredFeature +public class JmxCommonFeature implements InternalFeature { + @Override + public boolean isInConfiguration(IsInConfigurationAccess access) { + return VMInspectionOptions.hasJmxServerSupport() || VMInspectionOptions.hasJmxClientSupport(); + } + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport rci = ImageSingletons.lookup(org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport.class); + if (org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC <= 11) { + // Activation has been removed in JDK 17. + rci.initializeAtBuildTime("sun.rmi.server.Activation$ActivationSystemImpl_Stub", "JDK11 JMX support"); + } + rci.initializeAtBuildTime("jdk.management.jfr.SettingDescriptorInfo", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log$LogStreamLog", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log", "JMX support"); + rci.initializeAtBuildTime("java.rmi.server.LogStream", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.runtime.Log$LoggerLog", "JMX support"); + rci.initializeAtBuildTime("sun.rmi.server.Util", "JMX support"); + rci.initializeAtBuildTime("jdk.management.jfr.MBeanUtils", "JMX support"); + + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.StandardMBeanIntrospector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanLookup", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp", "JMX support"); + rci.initializeAtBuildTime("java.rmi.server.RemoteObjectInvocationHandler", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector", "JMX support"); + rci.initializeAtBuildTime("java.beans.Introspector", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.JavaBeansAccessor", "JMX support"); + + rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MBeanInstantiator", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ArrayNotificationBuffer", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.security.HashedPasswordManager", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXSubjectDomainCombiner", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerCommunicatorAdmin", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.defaults.JmxProperties", "JMX support"); + rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerNotifForwarder", "JMX support"); + + rci.initializeAtRunTime("sun.rmi.transport.ConnectionInputStream", "JMX support"); + rci.initializeAtRunTime("java.rmi.MarshalledObject$MarshalledObjectInputStream", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastRef2", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastRef", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.MarshalInputStream", "JMX support"); + rci.initializeAtRunTime("sun.rmi.runtime.NewThreadAction", "JMX support"); + rci.initializeAtRunTime("com.sun.jmx.remote.security.FileLoginModule", "JMX support"); + rci.initializeAtRunTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator$FileLoginConfig", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCImpl", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCAckHandler", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.GC", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.DGCClient", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.ObjectTable", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPEndpoint", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPChannel", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPTransport", "JMX support"); + rci.initializeAtRunTime("sun.rmi.transport.Transport", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.ObjID", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.UID", "JMX support"); + rci.initializeAtRunTime("sun.rmi.runtime.RuntimeUtil", "JMX support"); + rci.initializeAtRunTime("java.rmi.dgc.VMID", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.RMIClassLoader", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.LoaderHandler", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.RemoteServer", "JMX support"); + rci.initializeAtRunTime("sun.rmi.registry.RegistryImpl", "JMX support"); + rci.initializeAtRunTime("java.rmi.server.UnicastRemoteObject", "JMX support"); + rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef2", "JMX support"); + } + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + configureJNI(); + configureSerialization(access); + configureReflection(access); + configureProxy(access); + } + + private static void configureProxy(BeforeAnalysisAccess access) { + DynamicProxyRegistry dynamicProxySupport = ImageSingletons.lookup(DynamicProxyRegistry.class); + + dynamicProxySupport.addProxyClass(access.findClassByName("jdk.management.jfr.FlightRecorderMXBean"), + access.findClassByName("javax.management.NotificationEmitter")); + + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.RuntimeMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ClassLoadingMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryManagerMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.BufferPoolMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryPoolMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryMXBean"), access.findClassByName("javax.management.NotificationEmitter")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.UnixOperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.java.lang.management.CompilationMXBean")); + } + + private static void configureJNI() { + JNIRuntimeAccess.register(Arrays.class); + JNIRuntimeAccess.register(ReflectionUtil.lookupMethod(Arrays.class, "asList", Object[].class)); + } + + private static void configureSerialization(BeforeAnalysisAccess access) { + String[] classes = new String[]{ + "[B", "com.oracle.svm.core.jdk.UnsupportedFeatureError", + "java.io.IOException", "java.lang.Boolean", "java.lang.ClassCastException", "java.lang.Error", + "java.lang.Exception", "java.lang.IllegalArgumentException", "java.lang.IllegalStateException", + "java.lang.Integer", "[Ljava.lang.Integer;", "java.lang.Long", "java.lang.NoSuchMethodException", + "java.lang.Number", "[Ljava.lang.Object;", "java.lang.ReflectiveOperationException", + "java.lang.RuntimeException", "java.lang.SecurityException", "java.lang.StackTraceElement", + "[Ljava.lang.StackTraceElement;", "java.lang.String", "java.lang.Throwable", + "java.lang.UnsupportedOperationException", + "java.rmi.MarshalledObject", "[Ljava.rmi.MarshalledObject;", "java.rmi.RemoteException", + "java.rmi.ServerError", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", "java.rmi.server.ObjID", + "[Ljava.rmi.server.ObjID;", "java.rmi.server.RemoteObject", "java.rmi.server.RemoteStub", + "java.rmi.server.UID", "java.security.GeneralSecurityException", "java.util.ArrayList", + "java.util.Arrays$ArrayList", "java.util.Collections$EmptyList", + "java.util.Collections$UnmodifiableCollection", "java.util.Collections$UnmodifiableList", + "java.util.Collections$UnmodifiableRandomAccessList", + "java.util.EventObject", // Required for notifications + "java.util.HashMap", "java.util.HashSet", + "java.util.LinkedHashMap", "java.util.MissingResourceException", "java.util.TreeMap", + "java.util.Vector", "javax.management.Attribute", "javax.management.AttributeList", + "javax.management.AttributeNotFoundException", + "javax.management.AttributeChangeNotification", // Required for + // notifications + "javax.management.InstanceNotFoundException", + "javax.management.JMException", "javax.management.MBeanAttributeInfo", + "[Ljavax.management.MBeanAttributeInfo;", "[Ljavax.management.MBeanConstructorInfo;", + "javax.management.MBeanFeatureInfo", "javax.management.MBeanInfo", + "javax.management.MBeanNotificationInfo", "[Ljavax.management.MBeanNotificationInfo;", + "javax.management.MBeanOperationInfo", "[Ljavax.management.MBeanOperationInfo;", + "javax.management.MBeanParameterInfo", "[Ljavax.management.MBeanParameterInfo;", + "javax.management.Notification", // Required for notifications + "javax.management.NotificationFilterSupport", "javax.management.ObjectName", + "[Ljavax.management.ObjectName;", "javax.management.OperationsException", "javax.management.ReflectionException", + "javax.management.openmbean.ArrayType", "javax.management.openmbean.CompositeDataSupport", + "[Ljavax.management.openmbean.CompositeData;", "javax.management.openmbean.CompositeType", + "javax.management.openmbean.OpenMBeanAttributeInfoSupport", + "javax.management.openmbean.OpenMBeanParameterInfoSupport", "javax.management.openmbean.OpenType", + "javax.management.openmbean.SimpleType", "javax.management.openmbean.TabularDataSupport", + "javax.management.openmbean.TabularType", "javax.management.remote.NotificationResult", + "javax.management.remote.TargetedNotification", // Required for + // notifications + "[Ljavax.management.remote.TargetedNotification;", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServerImpl_Stub", "javax.management.RuntimeMBeanException", + "javax.rmi.ssl.SslRMIClientSocketFactory", // Required for SSL + "[Ljavax.security.auth.Subject;", "javax.security.auth.login.FailedLoginException", + "javax.security.auth.login.LoginException", "[J", "java.rmi.NoSuchObjectException", + "javax.management.JMRuntimeException", "javax.management.RuntimeErrorException" + }; + for (String clazz : classes) { + RuntimeSerialization.register(access.findClassByName(clazz)); + } + } + + private static void configureReflection(BeforeAnalysisAccess access) { + // Only JmxServerFeature, not JmxClientFeature, has registrations for platform MBeans + String[] classes = new String[]{ + "com.sun.crypto.provider.AESCipher$General", "com.sun.crypto.provider.ARCFOURCipher", + "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", "com.sun.crypto.provider.DESCipher", + "com.sun.crypto.provider.DESedeCipher", "com.sun.crypto.provider.DHParameters", + "com.sun.crypto.provider.HmacCore$HmacSHA256", + "com.sun.management.GcInfo", + "com.sun.management.internal.OperatingSystemImpl", + "javax.management.remote.rmi.RMIConnection", "com.sun.management.VMOption", + "javax.management.remote.rmi.RMIConnectionImpl_Stub", "javax.management.remote.rmi.RMIServer", + "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.registry.RegistryImpl_Stub", + "java.rmi.MarshalledObject", "java.rmi.Remote", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", + "java.rmi.registry.Registry", "java.rmi.server.ObjID", "java.rmi.server.RemoteObject", + "java.rmi.server.RemoteStub", "java.rmi.server.UID", "javax.management.openmbean.OpenType", + "java.lang.management.LockInfo", "java.lang.management.ManagementPermission", + "java.lang.management.MemoryUsage", "java.lang.management.MonitorInfo", + "java.lang.management.ThreadInfo", "java.security.SecureRandomParameters", + "javax.management.MBeanServerBuilder", "javax.management.NotificationBroadcaster", + "javax.management.NotificationEmitter", "javax.management.NotificationFilterSupport", + "javax.management.ObjectName", "jdk.management.jfr.ConfigurationInfo", + "jdk.management.jfr.EventTypeInfo", + "jdk.management.jfr.RecordingInfo", "jdk.management.jfr.SettingDescriptorInfo", + "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.transport.DGCImpl_Skel", + "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", + "sun.rmi.transport.DGCImpl_Stub" + }; + + String[] methods = new String[]{ + "com.sun.management.GcInfo", + "com.sun.management.VMOption", + "java.lang.management.MemoryUsage", "java.rmi.registry.Registry", + "javax.management.remote.rmi.RMIConnection", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServer", "javax.management.remote.rmi.RMIServerImpl_Stub", + "java.lang.management.MonitorInfo", + "java.lang.management.ThreadInfo", "jdk.management.jfr.ConfigurationInfo", + "jdk.management.jfr.EventTypeInfo", "jdk.management.jfr.RecordingInfo", + "jdk.management.jfr.SettingDescriptorInfo", "sun.rmi.registry.RegistryImpl_Stub", + "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", + "sun.rmi.transport.DGCImpl_Stub" + }; + + String[] fields = new String[]{"com.sun.management.GcInfo"}; + + String[] constructors = new String[]{ + "com.sun.management.internal.GarbageCollectorExtImpl", + "com.sun.management.internal.OperatingSystemImpl", "java.lang.management.ManagementPermission", + "javax.management.MBeanServerBuilder", "javax.management.remote.rmi.RMIConnectionImpl_Stub", + "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.transport.DGCImpl_Stub", + "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.registry.RegistryImpl_Stub", + "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl_Skel" + }; + + for (String clazz : classes) { + RuntimeReflection.register(access.findClassByName(clazz)); + } + for (String clazz : methods) { + RuntimeReflection.register(access.findClassByName(clazz).getMethods()); + } + for (String clazz : constructors) { + RuntimeReflection.register(access.findClassByName(clazz).getConstructors()); + } + for (String clazz : fields) { + RuntimeReflection.register(access.findClassByName(clazz).getFields()); + } + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java index ca4daf7ee3cc..aed69335457a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java @@ -29,7 +29,6 @@ import com.oracle.svm.core.feature.InternalFeature; import java.lang.management.PlatformManagedObject; -import java.util.Arrays; import java.util.Set; @@ -40,14 +39,11 @@ import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.configure.ResourcesRegistry; import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; -import com.oracle.svm.core.jni.JNIRuntimeAccess; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.hosted.RuntimeSerialization; import com.oracle.svm.core.jdk.RuntimeSupport; import com.oracle.svm.core.jdk.management.ManagementAgentStartupHook; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.VMInspectionOptions; -import com.oracle.svm.util.ReflectionUtil; @AutomaticallyRegisteredFeature public class JmxServerFeature implements InternalFeature { @@ -56,69 +52,6 @@ public boolean isInConfiguration(IsInConfigurationAccess access) { return VMInspectionOptions.hasJmxServerSupport(); } - @Override - public void afterRegistration(AfterRegistrationAccess access) { - org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport rci = ImageSingletons.lookup(org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport.class); - if (org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC <= 11) { - // Activation has been removed in JDK 17. - rci.initializeAtBuildTime("sun.rmi.server.Activation$ActivationSystemImpl_Stub", "JDK11 JMX support"); - } - rci.initializeAtBuildTime("jdk.management.jfr.SettingDescriptorInfo", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.runtime.Log$LogStreamLog", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.runtime.Log", "JMX support"); - rci.initializeAtBuildTime("java.rmi.server.LogStream", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.runtime.Log$LoggerLog", "JMX support"); - rci.initializeAtBuildTime("sun.rmi.server.Util", "JMX support"); - rci.initializeAtBuildTime("jdk.management.jfr.MBeanUtils", "JMX support"); - - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.StandardMBeanIntrospector", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanLookup", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp", "JMX support"); - rci.initializeAtBuildTime("java.rmi.server.RemoteObjectInvocationHandler", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector", "JMX support"); - rci.initializeAtBuildTime("java.beans.Introspector", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.JavaBeansAccessor", "JMX support"); - - rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.mbeanserver.MBeanInstantiator", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ArrayNotificationBuffer", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.security.HashedPasswordManager", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.security.JMXSubjectDomainCombiner", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerCommunicatorAdmin", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.defaults.JmxProperties", "JMX support"); - rci.initializeAtBuildTime("com.sun.jmx.remote.internal.ServerNotifForwarder", "JMX support"); - - rci.initializeAtRunTime("sun.rmi.transport.ConnectionInputStream", "JMX support"); - rci.initializeAtRunTime("java.rmi.MarshalledObject$MarshalledObjectInputStream", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastRef2", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastRef", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.MarshalInputStream", "JMX support"); - rci.initializeAtRunTime("sun.rmi.runtime.NewThreadAction", "JMX support"); - rci.initializeAtRunTime("com.sun.jmx.remote.security.FileLoginModule", "JMX support"); - rci.initializeAtRunTime("com.sun.jmx.remote.security.JMXPluggableAuthenticator$FileLoginConfig", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.DGCImpl", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.DGCAckHandler", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.GC", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.DGCClient", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.ObjectTable", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPEndpoint", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPChannel", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.tcp.TCPTransport", "JMX support"); - rci.initializeAtRunTime("sun.rmi.transport.Transport", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.ObjID", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.UID", "JMX support"); - rci.initializeAtRunTime("sun.rmi.runtime.RuntimeUtil", "JMX support"); - rci.initializeAtRunTime("java.rmi.dgc.VMID", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.RMIClassLoader", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.LoaderHandler", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.RemoteServer", "JMX support"); - rci.initializeAtRunTime("sun.rmi.registry.RegistryImpl", "JMX support"); - rci.initializeAtRunTime("java.rmi.server.UnicastRemoteObject", "JMX support"); - rci.initializeAtRunTime("sun.rmi.server.UnicastServerRef2", "JMX support"); - } - private static void handleNativeLibraries(BeforeAnalysisAccess access) { // This is required for password authentication. @@ -135,8 +68,6 @@ private static void handleNativeLibraries(BeforeAnalysisAccess access) { public void beforeAnalysis(BeforeAnalysisAccess access) { handleNativeLibraries(access); registerJMXAgentResources(); - configureJNI(); - configureSerialization(access); configureReflection(access); configureProxy(access); RuntimeSupport.getRuntimeSupport().addStartupHook(new ManagementAgentStartupHook()); @@ -159,84 +90,6 @@ private static void configureProxy(BeforeAnalysisAccess access) { access.findClassByName("java.rmi.registry.Registry")); dynamicProxySupport.addProxyClass(access.findClassByName("javax.management.remote.rmi.RMIServer")); - - dynamicProxySupport.addProxyClass(access.findClassByName("jdk.management.jfr.FlightRecorderMXBean"), - access.findClassByName("javax.management.NotificationEmitter")); - - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.RuntimeMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ClassLoadingMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.ThreadMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.ThreadMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.OperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.OperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryManagerMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.BufferPoolMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryPoolMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("java.lang.management.MemoryMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.UnixOperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(access.findClassByName("com.sun.management.java.lang.management.CompilationMXBean")); - } - - private static void configureJNI() { - JNIRuntimeAccess.register(Arrays.class); - JNIRuntimeAccess.register(ReflectionUtil.lookupMethod(Arrays.class, "asList", Object[].class)); - } - - private static void configureSerialization(BeforeAnalysisAccess access) { - String[] classes = new String[]{ - "[B", "com.oracle.svm.core.jdk.UnsupportedFeatureError", - "java.io.IOException", "java.lang.Boolean", "java.lang.ClassCastException", "java.lang.Error", - "java.lang.Exception", "java.lang.IllegalArgumentException", "java.lang.IllegalStateException", - "java.lang.Integer", "[Ljava.lang.Integer;", "java.lang.Long", "java.lang.NoSuchMethodException", - "java.lang.Number", "[Ljava.lang.Object;", "java.lang.ReflectiveOperationException", - "java.lang.RuntimeException", "java.lang.SecurityException", "java.lang.StackTraceElement", - "[Ljava.lang.StackTraceElement;", "java.lang.String", "java.lang.Throwable", - "java.lang.UnsupportedOperationException", - "java.rmi.MarshalledObject", "[Ljava.rmi.MarshalledObject;", "java.rmi.RemoteException", - "java.rmi.ServerError", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", "java.rmi.server.ObjID", - "[Ljava.rmi.server.ObjID;", "java.rmi.server.RemoteObject", "java.rmi.server.RemoteStub", - "java.rmi.server.UID", "java.security.GeneralSecurityException", "java.util.ArrayList", - "java.util.Arrays$ArrayList", "java.util.Collections$EmptyList", - "java.util.Collections$UnmodifiableCollection", "java.util.Collections$UnmodifiableList", - "java.util.Collections$UnmodifiableRandomAccessList", - "java.util.EventObject", // Required for notifications - "java.util.HashMap", "java.util.HashSet", - "java.util.LinkedHashMap", "java.util.MissingResourceException", "java.util.TreeMap", - "java.util.Vector", "javax.management.Attribute", "javax.management.AttributeList", - "javax.management.AttributeNotFoundException", - "javax.management.AttributeChangeNotification", // Required for - // notifications - "javax.management.InstanceNotFoundException", - "javax.management.JMException", "javax.management.MBeanAttributeInfo", - "[Ljavax.management.MBeanAttributeInfo;", "[Ljavax.management.MBeanConstructorInfo;", - "javax.management.MBeanFeatureInfo", "javax.management.MBeanInfo", - "javax.management.MBeanNotificationInfo", "[Ljavax.management.MBeanNotificationInfo;", - "javax.management.MBeanOperationInfo", "[Ljavax.management.MBeanOperationInfo;", - "javax.management.MBeanParameterInfo", "[Ljavax.management.MBeanParameterInfo;", - "javax.management.Notification", // Required for notifications - "javax.management.NotificationFilterSupport", "javax.management.ObjectName", - "[Ljavax.management.ObjectName;", "javax.management.OperationsException", "javax.management.ReflectionException", - "javax.management.openmbean.ArrayType", "javax.management.openmbean.CompositeDataSupport", - "[Ljavax.management.openmbean.CompositeData;", "javax.management.openmbean.CompositeType", - "javax.management.openmbean.OpenMBeanAttributeInfoSupport", - "javax.management.openmbean.OpenMBeanParameterInfoSupport", "javax.management.openmbean.OpenType", - "javax.management.openmbean.SimpleType", "javax.management.openmbean.TabularDataSupport", - "javax.management.openmbean.TabularType", "javax.management.remote.NotificationResult", - "javax.management.remote.TargetedNotification", // Required for - // notifications - "[Ljavax.management.remote.TargetedNotification;", "javax.management.remote.rmi.RMIConnectionImpl_Stub", - "javax.management.remote.rmi.RMIServerImpl_Stub", "javax.management.RuntimeMBeanException", - "javax.rmi.ssl.SslRMIClientSocketFactory", // Required for SSL - "[Ljavax.security.auth.Subject;", "javax.security.auth.login.FailedLoginException", - "javax.security.auth.login.LoginException", "[J", "java.rmi.NoSuchObjectException", - "javax.management.JMRuntimeException", "javax.management.RuntimeErrorException" - }; - - for (String clazz : classes) { - RuntimeSerialization.register(access.findClassByName(clazz)); - } } private static void configureReflection(BeforeAnalysisAccess access) { @@ -260,64 +113,25 @@ private static void configureReflection(BeforeAnalysisAccess access) { // Only JmxServerFeature, not JmxClientFeature, has registrations for platform MBeans String[] classes = new String[]{ - "com.sun.crypto.provider.AESCipher$General", "com.sun.crypto.provider.ARCFOURCipher", - "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", "com.sun.crypto.provider.DESCipher", - "com.sun.crypto.provider.DESedeCipher", "com.sun.crypto.provider.DHParameters", - "com.sun.crypto.provider.HmacCore$HmacSHA256", "com.sun.management.GarbageCollectorMXBean", - "com.sun.management.GcInfo", "com.sun.management.OperatingSystemMXBean", - "com.sun.management.internal.OperatingSystemImpl", "com.sun.management.ThreadMXBean", + "com.sun.management.GarbageCollectorMXBean", + "com.sun.management.OperatingSystemMXBean", + "com.sun.management.ThreadMXBean", "com.sun.management.UnixOperatingSystemMXBean", "java.lang.management.CompilationMXBean", "java.lang.management.GarbageCollectorMXBean", "java.lang.management.MemoryMXBean", "java.lang.management.MemoryManagerMXBean", "java.lang.management.MemoryPoolMXBean", "java.lang.management.RuntimeMXBean", "java.lang.management.BufferPoolMXBean", - "java.lang.management.ClassLoadingMXBean", "java.lang.management.PlatformLoggingMXBean", - "javax.management.remote.rmi.RMIConnection", "com.sun.management.VMOption", - "javax.management.remote.rmi.RMIConnectionImpl_Stub", "javax.management.remote.rmi.RMIServer", - "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.registry.RegistryImpl_Stub", - "java.rmi.MarshalledObject", "java.rmi.Remote", "java.rmi.dgc.Lease", "java.rmi.dgc.VMID", - "java.rmi.registry.Registry", "java.rmi.server.ObjID", "java.rmi.server.RemoteObject", - "java.rmi.server.RemoteStub", "java.rmi.server.UID", "javax.management.openmbean.OpenType", - "java.lang.management.LockInfo", "java.lang.management.ManagementPermission", - "java.lang.management.MemoryUsage", "java.lang.management.MonitorInfo", - "java.lang.management.ThreadInfo", "java.security.SecureRandomParameters", - "javax.management.MBeanServerBuilder", "javax.management.NotificationBroadcaster", - "javax.management.NotificationEmitter", "javax.management.NotificationFilterSupport", - "javax.management.ObjectName", "jdk.management.jfr.ConfigurationInfo", - "jdk.management.jfr.EventTypeInfo", "jdk.management.jfr.FlightRecorderMXBean", - "jdk.management.jfr.RecordingInfo", "jdk.management.jfr.SettingDescriptorInfo", - "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.transport.DGCImpl_Skel", - "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", - "sun.rmi.transport.DGCImpl_Stub" + "java.lang.management.ClassLoadingMXBean", "java.lang.management.PlatformLoggingMXBean" }; String[] methods = new String[]{ - "com.sun.management.GcInfo", "com.sun.management.OperatingSystemMXBean", + "com.sun.management.OperatingSystemMXBean", "com.sun.management.ThreadMXBean", "com.sun.management.UnixOperatingSystemMXBean", - "com.sun.management.VMOption", "java.lang.management.BufferPoolMXBean", + "java.lang.management.BufferPoolMXBean", "java.lang.management.ClassLoadingMXBean", "java.lang.management.CompilationMXBean", "java.lang.management.GarbageCollectorMXBean", "java.lang.management.MemoryMXBean", "java.lang.management.MemoryManagerMXBean", "java.lang.management.MemoryPoolMXBean", - "java.lang.management.MemoryUsage", "java.lang.management.RuntimeMXBean", - "java.lang.management.PlatformLoggingMXBean", "java.rmi.registry.Registry", - "javax.management.remote.rmi.RMIConnection", "javax.management.remote.rmi.RMIConnectionImpl_Stub", - "javax.management.remote.rmi.RMIServer", "javax.management.remote.rmi.RMIServerImpl_Stub", - "jdk.management.jfr.FlightRecorderMXBean", "java.lang.management.MonitorInfo", - "java.lang.management.ThreadInfo", "jdk.management.jfr.ConfigurationInfo", - "jdk.management.jfr.EventTypeInfo", "jdk.management.jfr.RecordingInfo", - "jdk.management.jfr.SettingDescriptorInfo", "sun.rmi.registry.RegistryImpl_Stub", - "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl", "sun.rmi.transport.DGCImpl_Skel", - "sun.rmi.transport.DGCImpl_Stub" - }; - - String[] fields = new String[]{"com.sun.management.GcInfo"}; - - String[] constructors = new String[]{ - "com.sun.management.internal.GarbageCollectorExtImpl", - "com.sun.management.internal.OperatingSystemImpl", "java.lang.management.ManagementPermission", - "javax.management.MBeanServerBuilder", "javax.management.remote.rmi.RMIConnectionImpl_Stub", - "javax.management.remote.rmi.RMIServerImpl_Stub", "sun.rmi.transport.DGCImpl_Stub", - "sun.rmi.registry.RegistryImpl_Skel", "sun.rmi.registry.RegistryImpl_Stub", - "sun.rmi.server.UnicastRef2", "sun.rmi.transport.DGCImpl_Skel" + "java.lang.management.RuntimeMXBean", + "java.lang.management.PlatformLoggingMXBean" }; for (String clazz : classes) { @@ -326,11 +140,5 @@ private static void configureReflection(BeforeAnalysisAccess access) { for (String clazz : methods) { RuntimeReflection.register(access.findClassByName(clazz).getMethods()); } - for (String clazz : constructors) { - RuntimeReflection.register(access.findClassByName(clazz).getConstructors()); - } - for (String clazz : fields) { - RuntimeReflection.register(access.findClassByName(clazz).getFields()); - } } } From 6da807a91097148927a9ba476690f44b605f75ad Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 12 Dec 2022 17:00:43 -0500 Subject: [PATCH 4/6] add initialization policies for FlightRecorder if JFR is enabled. --- .../svm/core/jdk/management/ManagementFeature.java | 11 +++++++++++ .../svm/core/jdk/management/ManagementSupport.java | 3 +-- .../com/oracle/svm/hosted/jdk/JmxServerFeature.java | 11 +++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java index 0dc38ef5a691..273958461742 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java @@ -54,6 +54,7 @@ import com.oracle.svm.core.thread.ThreadListenerSupportFeature; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.util.ReflectionUtil; +import com.oracle.svm.core.jfr.HasJfrSupport; /** See {@link ManagementSupport} for documentation. */ @AutomaticallyRegisteredFeature @@ -90,6 +91,16 @@ public void duringSetup(DuringSetupAccess access) { RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory$IdentityMapping"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.DescriptorCache"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.remote.util.ClassLogger"); + // Adding FlightRecorderMXBean in ManagementSupport class requires the below policies + if (HasJfrSupport.get()) { + RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp"); + RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector"); + RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector"); + RuntimeClassInitialization.initializeAtBuildTime("java.beans.Introspector"); + RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.JavaBeansAccessor"); + RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.StandardMBeanIntrospector"); + } + } /** diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java index ed0d09bdacb1..f5f40645ee18 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java @@ -158,7 +158,6 @@ public final class ManagementSupport implements ThreadListener { */ doAddPlatformManagedObjectSingleton(getOsMXBeanInterface(), (PlatformManagedObjectSupplier) this::getOsMXBean); doAddPlatformManagedObjectSingleton(FlightRecorderMXBean.class, (PlatformManagedObjectSupplier) this::getFlightRecorderMXBean); - } private static Class getOsMXBeanInterface() { @@ -368,7 +367,7 @@ List getPlatformMXBeans(Class mxbeanInte * {@linkplain #handleLazyPlatformManagedObjectSingleton special handling} when retrieving * stored platform objects. */ - private interface PlatformManagedObjectSupplier extends Supplier, PlatformManagedObject { + public interface PlatformManagedObjectSupplier extends Supplier, PlatformManagedObject { @Override default ObjectName getObjectName() { throw VMError.shouldNotReachHere(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java index aed69335457a..53d211a43d28 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java @@ -99,10 +99,13 @@ private static void configureReflection(BeforeAnalysisAccess access) { */ Set platformManagedObjects = com.oracle.svm.core.jdk.management.ManagementSupport .getSingleton().getPlatformManagedObjects(); - for (PlatformManagedObject p : platformManagedObjects) { // TODO: maybe its better to - // hardcode these because - // platform mbeans are lazily - // init at runtime + for (PlatformManagedObject p : platformManagedObjects) { + + // PlatformManagedObjectSupplier objects are lazily initialized at runtime. Skip them + // here. + if (p instanceof com.oracle.svm.core.jdk.management.ManagementSupport.PlatformManagedObjectSupplier) { + continue; + } Class clazz = p.getClass(); RuntimeReflection.register(clazz); RuntimeReflection.register(clazz.getDeclaredConstructors()); From a03b957acdfeb1639e1f48aff508ffffea878cd4 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 12 Dec 2022 20:18:03 -0500 Subject: [PATCH 5/6] add an additional initialization policy. Comment for clarity. --- .../svm/core/jdk/management/ManagementFeature.java | 9 +++++++-- .../com/oracle/svm/hosted/jdk/JmxServerFeature.java | 10 +++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java index 273958461742..ee6f4d7b36e7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java @@ -55,6 +55,7 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.util.ReflectionUtil; import com.oracle.svm.core.jfr.HasJfrSupport; +import com.oracle.svm.core.VMInspectionOptions; /** See {@link ManagementSupport} for documentation. */ @AutomaticallyRegisteredFeature @@ -91,14 +92,18 @@ public void duringSetup(DuringSetupAccess access) { RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory$IdentityMapping"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.DescriptorCache"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.remote.util.ClassLogger"); - // Adding FlightRecorderMXBean in ManagementSupport class requires the below policies - if (HasJfrSupport.get()) { + // Adding FlightRecorderMXBean in ManagementSupport class results in requiring the below + // policies. The policies are normally specified as part of JmxCommonFeature, + // but if JmxServer and JmxClient are not included in the image build, + // then we have to provide the policies here. + if (HasJfrSupport.get() && !VMInspectionOptions.hasJmxServerSupport() & !VMInspectionOptions.hasJmxClientSupport()) { RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector"); RuntimeClassInitialization.initializeAtBuildTime("java.beans.Introspector"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.JavaBeansAccessor"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.StandardMBeanIntrospector"); + RuntimeClassInitialization.initializeAtBuildTime("jdk.management.jfr.MBeanUtils"); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java index 53d211a43d28..094f640d40d7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java @@ -44,6 +44,7 @@ import com.oracle.svm.core.jdk.management.ManagementAgentStartupHook; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.VMInspectionOptions; +import com.oracle.svm.core.jdk.management.ManagementSupport; @AutomaticallyRegisteredFeature public class JmxServerFeature implements InternalFeature { @@ -97,13 +98,12 @@ private static void configureReflection(BeforeAnalysisAccess access) { * Register all the custom substrate MXBeans. They won't be accounted for by the native * image tracing agent so a user may not know they need to register them. */ - Set platformManagedObjects = com.oracle.svm.core.jdk.management.ManagementSupport - .getSingleton().getPlatformManagedObjects(); + Set platformManagedObjects = ManagementSupport.getSingleton().getPlatformManagedObjects(); for (PlatformManagedObject p : platformManagedObjects) { - // PlatformManagedObjectSupplier objects are lazily initialized at runtime. Skip them - // here. - if (p instanceof com.oracle.svm.core.jdk.management.ManagementSupport.PlatformManagedObjectSupplier) { + // The platformManagedObjects list contains some PlatformManagedObjectSupplier objects + // that are meant to help initialize some MXBeans at runtime. Skip them here. + if (p instanceof ManagementSupport.PlatformManagedObjectSupplier) { continue; } Class clazz = p.getClass(); From ddb62384b216e6595b23c4f443b56339eb17faed Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 12 Dec 2022 21:24:58 -0500 Subject: [PATCH 6/6] fix typo --- .../com/oracle/svm/core/jdk/management/ManagementFeature.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java index ee6f4d7b36e7..3d75055f33a7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java @@ -96,7 +96,7 @@ public void duringSetup(DuringSetupAccess access) { // policies. The policies are normally specified as part of JmxCommonFeature, // but if JmxServer and JmxClient are not included in the image build, // then we have to provide the policies here. - if (HasJfrSupport.get() && !VMInspectionOptions.hasJmxServerSupport() & !VMInspectionOptions.hasJmxClientSupport()) { + if (HasJfrSupport.get() && !VMInspectionOptions.hasJmxServerSupport() && !VMInspectionOptions.hasJmxClientSupport()) { RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.remote.util.EnvHelp"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.Introspector"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.MXBeanIntrospector");