diff --git a/espresso/mx.espresso/mx_espresso.py b/espresso/mx.espresso/mx_espresso.py index eb3efbeecf86..fed448a282d8 100644 --- a/espresso/mx.espresso/mx_espresso.py +++ b/espresso/mx.espresso/mx_espresso.py @@ -200,9 +200,9 @@ def _espresso_gate_runner(args, tasks): '-R:+EnableSignalHandling', '-R:+InstallSegfaultHandler', '--features=com.oracle.truffle.espresso.ref.FinalizationFeature', + '--enable-monitoring=threaddump', ] + mx_sdk_vm_impl.svm_experimental_options([ '-H:-JNIExportSymbols', - '-H:+DumpThreadStacksOnSignal', ]), ) diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index e7a6a40047b0..5e9f3998451c 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -7,6 +7,7 @@ This changelog summarizes major changes to GraalVM Native Image. * (GR-48343) Red Hat added support for the JFR events AllocationRequiringGC and SystemGC. * (GR-48612) Enable `--strict-image-heap` by default. The option is now deprecated and can be removed from your argument list. A blog post with more information will follow shortly. * (GR-48354) Remove native-image-agent legacy `build`-option +* (GR-49221) Support for thread dumps can now be enabled with `--enable-monitoring=threaddump`. The option `-H:±DumpThreadStacksOnSignal` is deprecated and marked for removal. ## GraalVM for JDK 21 (Internal Version 23.1.0) * (GR-35746) Lower the default aligned chunk size from 1 MB to 512 KB for the serial and epsilon GCs, reducing memory usage and image size in many cases. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DumpThreadStacksOnSignalFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DumpThreadStacksOnSignalFeature.java index 0fb26bbe6f5f..b4bd97ef37b2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DumpThreadStacksOnSignalFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DumpThreadStacksOnSignalFeature.java @@ -48,7 +48,7 @@ public class DumpThreadStacksOnSignalFeature implements InternalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { - return VMInspectionOptions.DumpThreadStacksOnSignal.getValue(); + return VMInspectionOptions.hasThreadDumpSupport(); } @Override 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 3fb496f4b0ca..2b221484625d 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 @@ -56,12 +56,20 @@ public final class VMInspectionOptions { private static final String MONITORING_JVMSTAT_NAME = "jvmstat"; 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 + + private static final String MONITORING_THREADDUMP_NAME = "threaddump"; + + 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_ALL_NAME, MONITORING_DEFAULT_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 + "', or '" + MONITORING_ALL_NAME + "' (deprecated behavior: defaults to '" + MONITORING_ALL_NAME + "' if no argument is provided)"; + static { + assert MONITORING_ALL_VALUES.stream().allMatch(v -> MONITORING_DEFAULT_NAME.equals(v) || MONITORING_ALLOWED_VALUES_TEXT.contains(v)) : "A value is missing in the user-facing help text"; + } + @APIOption(name = ENABLE_MONITORING_OPTION, defaultValue = MONITORING_DEFAULT_NAME) // - @Option(help = "Enable monitoring features that allow the VM to be inspected at run time. Comma-separated list can contain " + MONITORING_ALLOWED_VALUES + ". " + + @Option(help = "Enable monitoring features that allow the VM to be inspected at run time. Comma-separated list can contain " + MONITORING_ALLOWED_VALUES_TEXT + ". " + "For example: '--" + ENABLE_MONITORING_OPTION + "=" + MONITORING_HEAPDUMP_NAME + "," + MONITORING_JFR_NAME + "'.", type = OptionType.User) // public static final HostedOptionKey EnableMonitoringFeatures = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter(), VMInspectionOptions::validateEnableMonitoringFeatures); @@ -75,11 +83,10 @@ 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_JMXCLIENT_NAME, MONITORING_JMXSERVER_NAME, MONITORING_ALL_NAME, - MONITORING_DEFAULT_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); + MONITORING_ALLOWED_VALUES_TEXT); } } @@ -89,7 +96,7 @@ private static String getDefaultMonitoringCommandArgument() { } @Fold - public static String getHeapdumpsCommandArgument() { + public static String getHeapDumpCommandArgument() { return SubstrateOptionsParser.commandArgument(EnableMonitoringFeatures, MONITORING_HEAPDUMP_NAME); } @@ -121,7 +128,7 @@ public static boolean dumpImageHeap() { return true; } else { System.out.println("Unable to dump heap. Heap dumping is only supported on Linux and MacOS for native executables built with '" + - VMInspectionOptions.getHeapdumpsCommandArgument() + "'."); + VMInspectionOptions.getHeapDumpCommandArgument() + "'."); return false; } } @@ -151,15 +158,17 @@ public static boolean hasJmxClientSupport() { return hasAllOrKeywordMonitoringSupport(MONITORING_JMXCLIENT_NAME) && !Platform.includedIn(WINDOWS.class); } + @Fold + public static boolean hasThreadDumpSupport() { + return hasAllOrKeywordMonitoringSupport(MONITORING_THREADDUMP_NAME) || DeprecatedOptions.DumpThreadStacksOnSignal.getValue(); + } + @Option(help = "Dumps all runtime compiled methods on SIGUSR2.", type = OptionType.User) // public static final HostedOptionKey DumpRuntimeCompilationOnSignal = new HostedOptionKey<>(false); - @Option(help = "Dumps all thread stacktraces on SIGQUIT/SIGBREAK.", type = OptionType.User) // - public static final HostedOptionKey DumpThreadStacksOnSignal = new HostedOptionKey<>(false); - static class DeprecatedOptions { @Option(help = "Enables features that allow the VM to be inspected during run time.", type = OptionType.User, // - deprecated = true, deprecationMessage = "Please use --" + ENABLE_MONITORING_OPTION) // + deprecated = true, deprecationMessage = "Please use '--" + ENABLE_MONITORING_OPTION + "'") // static final HostedOptionKey AllowVMInspection = new HostedOptionKey<>(false) { @Override protected void onValueUpdate(EconomicMap, Object> values, Boolean oldValue, Boolean newValue) { @@ -168,6 +177,10 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o super.onValueUpdate(values, oldValue, newValue); } }; + + @Option(help = "Dumps all thread stacktraces on SIGQUIT/SIGBREAK.", type = OptionType.User, // + deprecated = true, deprecationMessage = "Please use '--" + ENABLE_MONITORING_OPTION + "=" + MONITORING_THREADDUMP_NAME + "'") // + public static final HostedOptionKey DumpThreadStacksOnSignal = new HostedOptionKey<>(false); } private VMInspectionOptions() {