Skip to content

[GR-40463] Add experimental support for JMX to Native Image. #5596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/mx.sdk/mx_sdk_vm_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1301,7 +1301,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',
'-H:+ReportExceptionStackTraces',
]
Expand Down
3 changes: 2 additions & 1 deletion substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (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-42375) Add `-H:±GenerateBuildArtifactsFile` option, which generates a `build-artifacts.json` file with a list of all artifacts produced by Native Image. `.build_artifacts.txt` files are now deprecated, disabled (can be re-enabled with env setting `NATIVE_IMAGE_DEPRECATED_BUILD_ARTIFACTS_TXT=true`), and will be removed in a future release.
* (GR-34179) Improved debugging support on Windows: Debug information now includes information about Java types (contributed by Red Hat).
* (GR-34179) Red Hat improved debugging support on Windows: Debug information now includes information about Java types.
* (GR-41096) Support services loaded through the `java.util.ServiceLoader.ModuleServicesLookupIterator`. An example of such service is the `com.sun.jndi.rmi.registry.RegistryContextFactory`.
* (GR-41912) The builder now generated reports for internal errors, which users can share when creating issues. By default, error reports follow the `svm_err_b_<timestamp>_pid<pid>.md` pattern and are created in the working directory. Use `-H:ErrorFile` to adjust the path or filename.
* (GR-36951) Add [RISC-V support](https://medium.com/p/899be38eddd9) for Native Image through the LLVM backend.
Expand All @@ -24,6 +24,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-43966) Remove analysis options -H:AnalysisStatisticsFile and -H:ImageBuildStatisticsFile. Output files are now written to fixed subdirectories relative to image location (reports/image_build_statistics.json).
* (GR-38414) BellSoft implemented the `MemoryPoolMXBean` for the serial and epsilon GCs.
* (GR-40641) Dynamic linking of AWT libraries on Linux.
* (GR-40463) Red Hat added experimental 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.
Expand Down
17 changes: 14 additions & 3 deletions substratevm/mx.substratevm/mx_substratevm_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import os
import re
from glob import glob
import tempfile

import zipfile
import mx
Expand Down Expand Up @@ -472,6 +473,12 @@ def collect_unique_dependencies(self, path, benchmark, exclude_libs):
return deps


def _empty_file():
with tempfile.NamedTemporaryFile(delete=False) as empty_file:
empty_file.write(b"")
return empty_file.name


# Note: If you wish to preserve the underlying benchmark stderr and stdout files after a run, you can pass the following argument: -preserve
# This argument can be added to either:
# 1. The agent stage: -Dnative-image.benchmark.extra-agent-run-arg=-preserve
Expand All @@ -490,13 +497,17 @@ def collect_unique_dependencies(self, path, benchmark, exclude_libs):
'xalan': ['--report-unsupported-elements-at-runtime',
'--initialize-at-build-time=org.apache.crimson.parser.Parser2'],
# There are two main issues with fop:
# 1. LoggingFeature is enabled by default, causing the LogManager configuration to be parsed at build-time. However, DaCapo Harness sets the logging config file path system property at runtime.
# This causes us to incorrectly parse the default log configuration, leading to output on stderr.
# 1. LoggingFeature is enabled by default, causing the LogManager configuration to be parsed at build-time. However
# DaCapo Harness sets the `java.util.logging.config.file` property at run-time. Therefore, we set
# `java.util.logging.config.file` to an empty file to avoid incorrectly parsing the default log configuration,
# leading to output on stderr. We cannot set it to scratch/fop.log as it would normally be, because the file does
# not exist and would fail the benchmark when assertions are enabled.
# 2. Native-image picks a different service provider than the JVM for javax.xml.transform.TransformerFactory.
# We can simply remove the jar containing that provider as it is not required for the benchmark to run.
'fop': ['--allow-incomplete-classpath',
'--report-unsupported-elements-at-runtime',
'-H:-EnableLoggingFeature',
'-esa', '-ea',
f"-Djava.util.logging.config.file={_empty_file()}",
'--initialize-at-run-time=org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList'],
'batik': ['--allow-incomplete-classpath']
}
Expand Down
12 changes: 12 additions & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@
"jdk.internal.perf",
"jdk.internal.ref",
"jdk.internal.reflect",
"jdk.internal.vm",
"jdk.internal.util",
],
"java.management": [
Expand All @@ -289,6 +290,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",
],
Expand Down Expand Up @@ -853,6 +860,9 @@
"requires": [
"java.compiler",
"jdk.jfr",
"java.management",
"jdk.management.jfr",
"java.rmi",
],
"requiresConcealed" : {
"java.base" : [
Expand Down Expand Up @@ -1342,6 +1352,8 @@
"java.net.http",
"jdk.sctp",
"[email protected]",
"jdk.management.agent",
"jdk.management.jfr",
],
"uses" : [
"org.graalvm.nativeimage.Platform",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 lastWholeHeapExaminedTimeMillis = -1;

@Platforms(Platform.HOSTED_ONLY.class)
GCImpl() {
Expand Down Expand Up @@ -291,6 +292,9 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co
}
scavenge(!complete);
verifyAfterGC();
if (complete) {
lastWholeHeapExaminedTimeMillis = System.currentTimeMillis();
}
} finally {
collectionTimer.close();
}
Expand Down Expand Up @@ -1186,6 +1190,17 @@ public UnsignedWord getCollectionEpoch() {
return collectionEpoch;
}

public long getMillisSinceLastWholeHeapExamined() {
long startMillis;
if (lastWholeHeapExaminedTimeMillis < 0) {
// no full GC has yet been run, use time since the first allocation
startMillis = HeapImpl.getChunkProvider().getFirstAllocationTime() / 1_000_000;
} else {
startMillis = lastWholeHeapExaminedTimeMillis;
}
return System.currentTimeMillis() - startMillis;
}

public GCAccounting getAccounting() {
return accounting;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,11 @@ public void dirtyAllReferencesOf(Object obj) {
}
}

@Override
public long getMillisSinceLastWholeHeapExamined() {
return getGCImpl().getMillisSinceLastWholeHeapExamined();
}

@Override
@Uninterruptible(reason = "Ensure that no GC can move the object to another chunk.", callerMustBe = true)
public long getIdentityHashSalt(Object obj) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -49,7 +49,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 +
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 +
"` (experimental), `" + MONITORING_JMXCLIENT_NAME + "` (experimental), or `" + MONITORING_ALL_NAME +
"` (deprecated behavior: defaults to `" + MONITORING_ALL_NAME + "` if no argument is provided)";

@APIOption(name = ENABLE_MONITORING_OPTION, defaultValue = MONITORING_DEFAULT_NAME) //
Expand All @@ -66,7 +69,8 @@ public static void validateEnableMonitoringFeatures(@SuppressWarnings("unused")
getDefaultMonitoringCommandArgument(),
SubstrateOptionsParser.commandArgument(EnableMonitoringFeatures, String.join(",", List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME))));
}
enabledFeatures.removeAll(List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_ALL_NAME, MONITORING_DEFAULT_NAME));
enabledFeatures.removeAll(List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_JMXCLIENT_NAME, MONITORING_JMXSERVER_NAME, MONITORING_ALL_NAME,
MONITORING_DEFAULT_NAME));
if (!enabledFeatures.isEmpty()) {
throw UserError.abort("The `%s` option contains invalid value(s): %s. It can only contain %s.", getDefaultMonitoringCommandArgument(), String.join(", ", enabledFeatures),
MONITORING_ALLOWED_VALUES);
Expand Down Expand Up @@ -111,6 +115,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<Boolean> DumpRuntimeCompilationOnSignal = new HostedOptionKey<>(false, VMInspectionOptions::validateOnSignalOption);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ public List<Class<?>> getLoadedClasses() {
@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 the longest time (in ms) that has elapsed since the last time that the whole heap has
* been examined by a garbage collection.
*/
public abstract long getMillisSinceLastWholeHeapExamined();

/**
* Retrieves a salt value for computing the {@linkplain System#identityHashCode identity hash
* code} of the passed object (and potentially other objects) from its address. The same salt
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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;

import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.heap.Heap;

@TargetClass(className = "sun.rmi.transport.GC")
final class Target_sun_rmi_transport_GC {
@Substitute
public static long maxObjectInspectionAge() {
return Heap.getHeap().getMillisSinceLastWholeHeapExamined();
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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 org.graalvm.compiler.api.replacements.Fold;

import com.oracle.svm.core.VMInspectionOptions;

public class JmxIncluded implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
return get();
}

@Fold
public static boolean get() {
return VMInspectionOptions.hasJmxServerSupport() || VMInspectionOptions.hasJmxClientSupport();
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading