From 42fa59e2b3b557747b137936ff0f5b9b6b3f1a1f Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Wed, 11 Sep 2024 12:03:31 +0200 Subject: [PATCH] Update VisualVM documentation and add more validation for the option '--enable-monitoring'. --- docs/tools/visualvm.md | 18 +++++++++++------- .../oracle/svm/core/VMInspectionOptions.java | 14 +++++++++++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/docs/tools/visualvm.md b/docs/tools/visualvm.md index 040d0b8d4668..40c107b13975 100644 --- a/docs/tools/visualvm.md +++ b/docs/tools/visualvm.md @@ -24,15 +24,19 @@ VisualVM enables powerful yet easy-to-use Java tooling which includes heap analy Immediately after startup, the tool shows all locally running Java processes in the Applications area, including the VisualVM process, itself. +### Using VisualVM with GraalVM Native Executables + +> Note: VisualVM support for GraalVM native executables is not yet available on Windows. + +When using GraalVM [Native Image](../reference-manual/native-image/README.md), VisualVM support is disabled by default. +VisualVM support can be enabled when building a native executable with the option `--enable-monitoring=jvmstat,heapdump`: +```shell +native-image --enable-monitoring=jvmstat,heapdump JavaApplication +``` + ### Capture a Heap Dump -To capture a heap dump of, for example, a Ruby application for later analysis, start your application and let it run for a few seconds to warm up. +To capture a heap dump for later analysis, start your application and let it run for a few seconds to warm up. Then right-click its process in VisualVM and invoke the Heap Dump action. -A new heap viewer for the Ruby process opens. - -__Note:__ Heap dump support must be explicitly enabled when using [Native Image](../reference-manual/native-image/README.md). -Add the `--enable-monitoring=heapdump,jvmstat` option when invoking the `native-image` tool to enable the heap dump feature and allow VisualVM to detect native executables via `jvmstat`. -This way your application will handle signals and capture a heap dump when it receives the `SIGUSR1` signal. -See the [Generating Native Heap Dumps](../reference-manual/native-image/guides/create-heap-dump-from-native-executable.md) page for details on capturing heap dumps from a native image process. ### Analyzing Objects Initially the Summary view for the Java heap is displayed. 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 794755a206c3..27e7fbd6ff29 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 @@ -37,8 +37,8 @@ import com.oracle.svm.core.heap.dump.HeapDumping; import com.oracle.svm.core.jdk.management.ManagementAgentModule; import com.oracle.svm.core.option.APIOption; -import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.AccumulatingLocatableMultiOptionValue; +import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.RuntimeOptionKey; import com.oracle.svm.core.option.SubstrateOptionsParser; import com.oracle.svm.core.util.UserError; @@ -63,6 +63,7 @@ public final class VMInspectionOptions { private static final List MONITORING_ALL_VALUES = List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_JMXCLIENT_NAME, MONITORING_JMXSERVER_NAME, MONITORING_THREADDUMP_NAME, MONITORING_NMT_NAME, MONITORING_ALL_NAME, MONITORING_DEFAULT_NAME); + private static final List NOT_SUPPORTED_ON_WINDOWS = List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_JMXCLIENT_NAME, MONITORING_JMXSERVER_NAME); private static final String MONITORING_ALLOWED_VALUES_TEXT = "'" + MONITORING_HEAPDUMP_NAME + "', '" + MONITORING_JFR_NAME + "', '" + MONITORING_JVMSTAT_NAME + "', '" + MONITORING_JMXSERVER_NAME + "' (experimental), '" + MONITORING_JMXCLIENT_NAME + "' (experimental), '" + MONITORING_THREADDUMP_NAME + "', '" + MONITORING_NMT_NAME + "' (experimental), or '" + MONITORING_ALL_NAME + "' (deprecated behavior: defaults to '" + MONITORING_ALL_NAME + "' if no argument is provided)"; @@ -93,11 +94,22 @@ public static void validateEnableMonitoringFeatures(@SuppressWarnings("unused") getDefaultMonitoringCommandArgument(), SubstrateOptionsParser.commandArgument(EnableMonitoringFeatures, String.join(",", List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME)))); } + enabledFeatures.removeAll(MONITORING_ALL_VALUES); 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_TEXT); } + + if (Platform.includedIn(WINDOWS.class)) { + Set notSupported = getEnabledMonitoringFeatures(); + notSupported.retainAll(NOT_SUPPORTED_ON_WINDOWS); + if (!notSupported.isEmpty()) { + String warning = String.format("the option '%s' contains value(s) that are not supported on Windows: %s. Those values will be ignored.", getDefaultMonitoringCommandArgument(), + String.join(", ", notSupported)); + LogUtils.warning(warning); + } + } } @Platforms(Platform.HOSTED_ONLY.class)