From 63b2fcdc2a79efb6df120f88dac18972ad71d59b Mon Sep 17 00:00:00 2001 From: daguimu Date: Wed, 25 Mar 2026 04:11:45 +0800 Subject: [PATCH 1/2] fix: improve vmoption command compatibility with JDK 21 On JDK 21, vmoption command fails with 'Error during setting vm option: sun.management.Flag' due to JDK module system restrictions on internal management APIs introduced in JDK 9+. Changes: - Extract getHotSpotDiagnosticMXBean() helper that tries the direct ManagementFactory.getPlatformMXBean() path first, then falls back to JMX.newMXBeanProxy() via MBeanServer, which has better module compatibility on JDK 9+ - Improve error message to include actionable hint when sun.management access fails, suggesting --add-opens java.management/sun.management=ALL-UNNAMED - Wrap complete() method in try/catch to handle errors gracefully Fixes #3081 --- .../command/basic1000/VMOptionCommand.java | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java index 739e4513330..b3fb1fe4592 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java @@ -5,6 +5,10 @@ import java.util.Collections; import java.util.List; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.JMX; + import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.sun.management.HotSpotDiagnosticMXBean; @@ -42,6 +46,25 @@ public class VMOptionCommand extends AnnotatedCommand { private static final Logger logger = LoggerFactory.getLogger(VMOptionCommand.class); + private static final String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME = "com.sun.management:type=HotSpotDiagnostic"; + + private static HotSpotDiagnosticMXBean getHotSpotDiagnosticMXBean() throws Exception { + // Primary path: direct ManagementFactory lookup + try { + HotSpotDiagnosticMXBean bean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); + if (bean != null) { + return bean; + } + } catch (Throwable t) { + // fall through to JMX fallback + } + // Fallback: look up via MBeanServer (better module compatibility on JDK 9+) + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + return JMX.newMXBeanProxy(server, + new ObjectName(HOTSPOT_DIAGNOSTIC_MXBEAN_NAME), + HotSpotDiagnosticMXBean.class); + } + private String name; private String value; @@ -64,8 +87,7 @@ public void process(CommandProcess process) { private static void run(CommandProcess process, String name, String value) { try { - HotSpotDiagnosticMXBean hotSpotDiagnosticMXBean = ManagementFactory - .getPlatformMXBean(HotSpotDiagnosticMXBean.class); + HotSpotDiagnosticMXBean hotSpotDiagnosticMXBean = getHotSpotDiagnosticMXBean(); if (StringUtils.isBlank(name) && StringUtils.isBlank(value)) { // show all options @@ -92,19 +114,29 @@ private static void run(CommandProcess process, String name, String value) { process.end(); } catch (Throwable t) { logger.error("Error during setting vm option", t); - process.end(-1, "Error during setting vm option: " + t.getMessage()); + String msg = t.getMessage(); + String hint = ""; + if (msg != null && (msg.contains("sun.management") || msg.contains("sun/management"))) { + hint = " (JDK module access issue: try adding" + + " --add-opens java.management/sun.management=ALL-UNNAMED" + + " to the target JVM startup arguments)"; + } + process.end(-1, "Error during setting vm option: " + msg + hint); } } @Override public void complete(Completion completion) { - HotSpotDiagnosticMXBean hotSpotDiagnosticMXBean = ManagementFactory - .getPlatformMXBean(HotSpotDiagnosticMXBean.class); - List diagnosticOptions = hotSpotDiagnosticMXBean.getDiagnosticOptions(); - List names = new ArrayList(diagnosticOptions.size()); - for (VMOption option : diagnosticOptions) { - names.add(option.getName()); + try { + HotSpotDiagnosticMXBean hotSpotDiagnosticMXBean = getHotSpotDiagnosticMXBean(); + List diagnosticOptions = hotSpotDiagnosticMXBean.getDiagnosticOptions(); + List names = new ArrayList(diagnosticOptions.size()); + for (VMOption option : diagnosticOptions) { + names.add(option.getName()); + } + CompletionUtils.complete(completion, names); + } catch (Throwable t) { + logger.error("Error during completing vmoption", t); } - CompletionUtils.complete(completion, names); } } From 4c9bb84671383cd355154d9bd1d701fb3821b907 Mon Sep 17 00:00:00 2001 From: daguimu Date: Wed, 25 Mar 2026 04:27:28 +0800 Subject: [PATCH 2/2] fix: add debug logging for primary MXBean lookup failure in VMOptionCommand Log the reason when ManagementFactory.getPlatformMXBean() fails before falling back to MBeanServer proxy, to aid debugging on JDK 9+ environments. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../taobao/arthas/core/command/basic1000/VMOptionCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java index b3fb1fe4592..713759e3bfd 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java @@ -56,7 +56,7 @@ private static HotSpotDiagnosticMXBean getHotSpotDiagnosticMXBean() throws Excep return bean; } } catch (Throwable t) { - // fall through to JMX fallback + logger.debug("Primary HotSpotDiagnosticMXBean lookup failed, trying MBeanServer fallback", t); } // Fallback: look up via MBeanServer (better module compatibility on JDK 9+) MBeanServer server = ManagementFactory.getPlatformMBeanServer();