Skip to content

Commit 0056e64

Browse files
committed
[GR-40463] Add experimental support for JMX to Native Image.
PullRequest: graal/13172
2 parents e3196bf + f564814 commit 0056e64

27 files changed

+1423
-37
lines changed

sdk/mx.sdk/mx_sdk_vm_impl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@ def contents(self):
13011301
if isinstance(image_config, mx_sdk.LauncherConfig) or (isinstance(image_config, mx_sdk.LanguageLibraryConfig) and image_config.launchers):
13021302
build_args += [
13031303
'--install-exit-handlers',
1304-
'--enable-monitoring',
1304+
'--enable-monitoring=jvmstat,heapdump,jfr',
13051305
'-H:+DumpRuntimeCompilationOnSignal',
13061306
'-H:+ReportExceptionStackTraces',
13071307
]

substratevm/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1010
* (GR-41100) Add support for `-XX:HeapDumpPath` to control where heap dumps are created.
1111
* (GR-42148) Adjust build output to report types (primitives, classes, interfaces, and arrays) instead of classes and revise the output schema of `-H:BuildOutputJSONFile`.
1212
* (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.
13-
* (GR-34179) Improved debugging support on Windows: Debug information now includes information about Java types (contributed by Red Hat).
13+
* (GR-34179) Red Hat improved debugging support on Windows: Debug information now includes information about Java types.
1414
* (GR-41096) Support services loaded through the `java.util.ServiceLoader.ModuleServicesLookupIterator`. An example of such service is the `com.sun.jndi.rmi.registry.RegistryContextFactory`.
1515
* (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.
1616
* (GR-36951) Add [RISC-V support](https://medium.com/p/899be38eddd9) for Native Image through the LLVM backend.
@@ -24,6 +24,7 @@ This changelog summarizes major changes to GraalVM Native Image.
2424
* (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).
2525
* (GR-38414) BellSoft implemented the `MemoryPoolMXBean` for the serial and epsilon GCs.
2626
* (GR-40641) Dynamic linking of AWT libraries on Linux.
27+
* (GR-40463) Red Hat added experimental support for JMX, which can be enabled with the `--enable-monitoring` option (e.g. `--enable-monitoring=jmxclient,jmxserver`).
2728

2829
## Version 22.3.0
2930
* (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option.

substratevm/mx.substratevm/mx_substratevm_benchmark.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import os
3232
import re
3333
from glob import glob
34+
import tempfile
3435

3536
import zipfile
3637
import mx
@@ -472,6 +473,12 @@ def collect_unique_dependencies(self, path, benchmark, exclude_libs):
472473
return deps
473474

474475

476+
def _empty_file():
477+
with tempfile.NamedTemporaryFile(delete=False) as empty_file:
478+
empty_file.write(b"")
479+
return empty_file.name
480+
481+
475482
# Note: If you wish to preserve the underlying benchmark stderr and stdout files after a run, you can pass the following argument: -preserve
476483
# This argument can be added to either:
477484
# 1. The agent stage: -Dnative-image.benchmark.extra-agent-run-arg=-preserve
@@ -490,13 +497,17 @@ def collect_unique_dependencies(self, path, benchmark, exclude_libs):
490497
'xalan': ['--report-unsupported-elements-at-runtime',
491498
'--initialize-at-build-time=org.apache.crimson.parser.Parser2'],
492499
# There are two main issues with fop:
493-
# 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.
494-
# This causes us to incorrectly parse the default log configuration, leading to output on stderr.
500+
# 1. LoggingFeature is enabled by default, causing the LogManager configuration to be parsed at build-time. However
501+
# DaCapo Harness sets the `java.util.logging.config.file` property at run-time. Therefore, we set
502+
# `java.util.logging.config.file` to an empty file to avoid incorrectly parsing the default log configuration,
503+
# leading to output on stderr. We cannot set it to scratch/fop.log as it would normally be, because the file does
504+
# not exist and would fail the benchmark when assertions are enabled.
495505
# 2. Native-image picks a different service provider than the JVM for javax.xml.transform.TransformerFactory.
496506
# We can simply remove the jar containing that provider as it is not required for the benchmark to run.
497507
'fop': ['--allow-incomplete-classpath',
498508
'--report-unsupported-elements-at-runtime',
499-
'-H:-EnableLoggingFeature',
509+
'-esa', '-ea',
510+
f"-Djava.util.logging.config.file={_empty_file()}",
500511
'--initialize-at-run-time=org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList'],
501512
'batik': ['--allow-incomplete-classpath']
502513
}

substratevm/mx.substratevm/suite.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@
280280
"jdk.internal.perf",
281281
"jdk.internal.ref",
282282
"jdk.internal.reflect",
283+
"jdk.internal.vm",
283284
"jdk.internal.util",
284285
],
285286
"java.management": [
@@ -289,6 +290,12 @@
289290
"jdk.management": [
290291
"com.sun.management.internal"
291292
],
293+
"jdk.management.agent": [
294+
"jdk.internal.agent",
295+
],
296+
"jdk.management.jfr": [
297+
"jdk.management.jfr"
298+
],
292299
"jdk.httpserver@19+": [
293300
"sun.net.httpserver.simpleserver",
294301
],
@@ -853,6 +860,9 @@
853860
"requires": [
854861
"java.compiler",
855862
"jdk.jfr",
863+
"java.management",
864+
"jdk.management.jfr",
865+
"java.rmi",
856866
],
857867
"requiresConcealed" : {
858868
"java.base" : [
@@ -1342,6 +1352,8 @@
13421352
"java.net.http",
13431353
"jdk.sctp",
13441354
1355+
"jdk.management.agent",
1356+
"jdk.management.jfr",
13451357
],
13461358
"uses" : [
13471359
"org.graalvm.nativeimage.Platform",

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public final class GCImpl implements GC {
115115
private UnsignedWord sizeBefore = WordFactory.zero();
116116
private boolean collectionInProgress = false;
117117
private UnsignedWord collectionEpoch = WordFactory.zero();
118+
private long lastWholeHeapExaminedTimeMillis = -1;
118119

119120
@Platforms(Platform.HOSTED_ONLY.class)
120121
GCImpl() {
@@ -291,6 +292,9 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co
291292
}
292293
scavenge(!complete);
293294
verifyAfterGC();
295+
if (complete) {
296+
lastWholeHeapExaminedTimeMillis = System.currentTimeMillis();
297+
}
294298
} finally {
295299
collectionTimer.close();
296300
}
@@ -1186,6 +1190,17 @@ public UnsignedWord getCollectionEpoch() {
11861190
return collectionEpoch;
11871191
}
11881192

1193+
public long getMillisSinceLastWholeHeapExamined() {
1194+
long startMillis;
1195+
if (lastWholeHeapExaminedTimeMillis < 0) {
1196+
// no full GC has yet been run, use time since the first allocation
1197+
startMillis = HeapImpl.getChunkProvider().getFirstAllocationTime() / 1_000_000;
1198+
} else {
1199+
startMillis = lastWholeHeapExaminedTimeMillis;
1200+
}
1201+
return System.currentTimeMillis() - startMillis;
1202+
}
1203+
11891204
public GCAccounting getAccounting() {
11901205
return accounting;
11911206
}

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,11 @@ public void dirtyAllReferencesOf(Object obj) {
687687
}
688688
}
689689

690+
@Override
691+
public long getMillisSinceLastWholeHeapExamined() {
692+
return getGCImpl().getMillisSinceLastWholeHeapExamined();
693+
}
694+
690695
@Override
691696
@Uninterruptible(reason = "Ensure that no GC can move the object to another chunk.", callerMustBe = true)
692697
public long getIdentityHashSalt(Object obj) {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspectionOptions.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,10 @@ public final class VMInspectionOptions {
4949
private static final String MONITORING_HEAPDUMP_NAME = "heapdump";
5050
private static final String MONITORING_JFR_NAME = "jfr";
5151
private static final String MONITORING_JVMSTAT_NAME = "jvmstat";
52-
private static final String MONITORING_ALLOWED_VALUES = "`" + MONITORING_HEAPDUMP_NAME + "`, `" + MONITORING_JFR_NAME + "`, `" + MONITORING_JVMSTAT_NAME + "`, or `" + MONITORING_ALL_NAME +
52+
private static final String MONITORING_JMXCLIENT_NAME = "jmxclient";
53+
private static final String MONITORING_JMXSERVER_NAME = "jmxserver";
54+
private static final String MONITORING_ALLOWED_VALUES = "`" + MONITORING_HEAPDUMP_NAME + "`, `" + MONITORING_JFR_NAME + "`, `" + MONITORING_JVMSTAT_NAME + "`, `" + MONITORING_JMXSERVER_NAME +
55+
"` (experimental), `" + MONITORING_JMXCLIENT_NAME + "` (experimental), or `" + MONITORING_ALL_NAME +
5356
"` (deprecated behavior: defaults to `" + MONITORING_ALL_NAME + "` if no argument is provided)";
5457

5558
@APIOption(name = ENABLE_MONITORING_OPTION, defaultValue = MONITORING_DEFAULT_NAME) //
@@ -66,7 +69,8 @@ public static void validateEnableMonitoringFeatures(@SuppressWarnings("unused")
6669
getDefaultMonitoringCommandArgument(),
6770
SubstrateOptionsParser.commandArgument(EnableMonitoringFeatures, String.join(",", List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME))));
6871
}
69-
enabledFeatures.removeAll(List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_ALL_NAME, MONITORING_DEFAULT_NAME));
72+
enabledFeatures.removeAll(List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_JMXCLIENT_NAME, MONITORING_JMXSERVER_NAME, MONITORING_ALL_NAME,
73+
MONITORING_DEFAULT_NAME));
7074
if (!enabledFeatures.isEmpty()) {
7175
throw UserError.abort("The `%s` option contains invalid value(s): %s. It can only contain %s.", getDefaultMonitoringCommandArgument(), String.join(", ", enabledFeatures),
7276
MONITORING_ALLOWED_VALUES);
@@ -111,6 +115,16 @@ public static boolean hasJvmstatSupport() {
111115
return hasAllOrKeywordMonitoringSupport(MONITORING_JVMSTAT_NAME) && !Platform.includedIn(WINDOWS.class);
112116
}
113117

118+
@Fold
119+
public static boolean hasJmxServerSupport() {
120+
return hasAllOrKeywordMonitoringSupport(MONITORING_JMXSERVER_NAME) && !Platform.includedIn(WINDOWS.class);
121+
}
122+
123+
@Fold
124+
public static boolean hasJmxClientSupport() {
125+
return hasAllOrKeywordMonitoringSupport(MONITORING_JMXCLIENT_NAME) && !Platform.includedIn(WINDOWS.class);
126+
}
127+
114128
@Option(help = "Dumps all runtime compiled methods on SIGUSR2.", type = OptionType.User) //
115129
public static final HostedOptionKey<Boolean> DumpRuntimeCompilationOnSignal = new HostedOptionKey<>(false, VMInspectionOptions::validateOnSignalOption);
116130

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ public List<Class<?>> getLoadedClasses() {
246246
@Uninterruptible(reason = "Ensure that no GC can occur between modification of the object and this call.", callerMustBe = true)
247247
public abstract void dirtyAllReferencesOf(Object obj);
248248

249+
/**
250+
* Returns the longest time (in ms) that has elapsed since the last time that the whole heap has
251+
* been examined by a garbage collection.
252+
*/
253+
public abstract long getMillisSinceLastWholeHeapExamined();
254+
249255
/**
250256
* Retrieves a salt value for computing the {@linkplain System#identityHashCode identity hash
251257
* code} of the passed object (and potentially other objects) from its address. The same salt
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jdk;
28+
29+
import com.oracle.svm.core.annotate.Substitute;
30+
import com.oracle.svm.core.annotate.TargetClass;
31+
import com.oracle.svm.core.heap.Heap;
32+
33+
@TargetClass(className = "sun.rmi.transport.GC")
34+
final class Target_sun_rmi_transport_GC {
35+
@Substitute
36+
public static long maxObjectInspectionAge() {
37+
return Heap.getHeap().getMillisSinceLastWholeHeapExamined();
38+
}
39+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2022, 2022, Red Hat Inc. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
package com.oracle.svm.core.jdk.management;
28+
29+
import java.util.function.BooleanSupplier;
30+
import com.oracle.svm.core.VMInspectionOptions;
31+
32+
public class JmxClientNotIncluded implements BooleanSupplier {
33+
@Override
34+
public boolean getAsBoolean() {
35+
return !VMInspectionOptions.hasJmxClientSupport();
36+
}
37+
}

0 commit comments

Comments
 (0)