diff --git a/core/src/main/java/com/taobao/arthas/core/GlobalOptions.java b/core/src/main/java/com/taobao/arthas/core/GlobalOptions.java index 6e623e00c0c..f9b9f0df36c 100644 --- a/core/src/main/java/com/taobao/arthas/core/GlobalOptions.java +++ b/core/src/main/java/com/taobao/arthas/core/GlobalOptions.java @@ -1,6 +1,11 @@ package com.taobao.arthas.core; +import java.lang.reflect.Field; + import com.taobao.arthas.common.JavaVersionUtils; +import com.taobao.arthas.common.UnsafeUtils; + +import ognl.OgnlRuntime; /** * 全局开关 @@ -128,7 +133,8 @@ public class GlobalOptions { public static volatile boolean verbose = false; /** - * 是否打开strict 开关 + * 是否打开strict 开关。更新时注意 ognl 里的配置需要同步修改 + * @see ognl.OgnlRuntime#getUseStricterInvocationValue() */ @Option(level = 1, name = "strict", @@ -136,4 +142,20 @@ public class GlobalOptions { description = STRICT_MESSAGE ) public static volatile boolean strict = true; + + public static void updateOnglStrict(boolean strict) { + try { + Field field = OgnlRuntime.class.getDeclaredField("_useStricterInvocation"); + field.setAccessible(true); + // 获取字段的内存偏移量和基址 + Object staticFieldBase = UnsafeUtils.UNSAFE.staticFieldBase(field); + long staticFieldOffset = UnsafeUtils.UNSAFE.staticFieldOffset(field); + + // 修改字段的值 + UnsafeUtils.UNSAFE.putBoolean(staticFieldBase, staticFieldOffset, strict); + } catch (NoSuchFieldException | SecurityException e) { + // ignore + } + } + } diff --git a/core/src/main/java/com/taobao/arthas/core/command/basic1000/OptionsCommand.java b/core/src/main/java/com/taobao/arthas/core/command/basic1000/OptionsCommand.java index 14a0a6174ad..b463975394f 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/basic1000/OptionsCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/basic1000/OptionsCommand.java @@ -155,6 +155,11 @@ private ExitStatus processChangeNameValue(CommandProcess process) throws Illegal return ExitStatus.failure(-1, format("Options[%s] type[%s] was unsupported.", optionName, type.getSimpleName())); } + // FIXME hack for ongl strict + if (field.getName().equals("strict")) { + GlobalOptions.updateOnglStrict(Boolean.valueOf(optionValue)); + logger.info("update ongl strict to: {}", optionValue); + } } catch (Throwable t) { return ExitStatus.failure(-1, format("Cannot cast option value[%s] to type[%s].", optionValue, type.getSimpleName())); } diff --git a/core/src/test/java/com/taobao/arthas/core/GlobalOptionsTest.java b/core/src/test/java/com/taobao/arthas/core/GlobalOptionsTest.java new file mode 100644 index 00000000000..f915d6c616a --- /dev/null +++ b/core/src/test/java/com/taobao/arthas/core/GlobalOptionsTest.java @@ -0,0 +1,18 @@ +package com.taobao.arthas.core; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import ognl.OgnlRuntime; + +class GlobalOptionsTest { + + @Test + void test() { + GlobalOptions.updateOnglStrict(true); + Assertions.assertThat(OgnlRuntime.getUseStricterInvocationValue()).isTrue(); + GlobalOptions.updateOnglStrict(false); + Assertions.assertThat(OgnlRuntime.getUseStricterInvocationValue()).isFalse(); + } + +}