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 f9b9f0df3..6ba592a95 100644 --- a/core/src/main/java/com/taobao/arthas/core/GlobalOptions.java +++ b/core/src/main/java/com/taobao/arthas/core/GlobalOptions.java @@ -2,6 +2,7 @@ package com.taobao.arthas.core; import java.lang.reflect.Field; +import com.taobao.arthas.common.ArthasConstants; import com.taobao.arthas.common.JavaVersionUtils; import com.taobao.arthas.common.UnsafeUtils; @@ -66,6 +67,16 @@ public class GlobalOptions { ) public static volatile boolean isUsingJson = false; + /** + * ObjectView 输出大小限制(字节) + */ + @Option(level = 1, + name = "object-size-limit", + summary = "Option to control ObjectView output size limit", + description = "Upper size limit in bytes for ObjectView output, must be greater than 0. Default value is 10 * 1024 * 1024." + ) + public static volatile int objectSizeLimit = ArthasConstants.MAX_HTTP_CONTENT_LENGTH; + /** * 是否关闭子类 */ 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 b46397539..bfd899231 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 @@ -136,39 +136,55 @@ public class OptionsCommand extends AnnotatedCommand { try { // try to case string to type if (isIn(type, int.class, Integer.class)) { - FieldUtils.writeStaticField(field, afterValue = Integer.valueOf(optionValue)); + afterValue = Integer.valueOf(optionValue); } else if (isIn(type, long.class, Long.class)) { - FieldUtils.writeStaticField(field, afterValue = Long.valueOf(optionValue)); + afterValue = Long.valueOf(optionValue); } else if (isIn(type, boolean.class, Boolean.class)) { - FieldUtils.writeStaticField(field, afterValue = Boolean.valueOf(optionValue)); + afterValue = Boolean.valueOf(optionValue); } else if (isIn(type, double.class, Double.class)) { - FieldUtils.writeStaticField(field, afterValue = Double.valueOf(optionValue)); + afterValue = Double.valueOf(optionValue); } else if (isIn(type, float.class, Float.class)) { - FieldUtils.writeStaticField(field, afterValue = Float.valueOf(optionValue)); + afterValue = Float.valueOf(optionValue); } else if (isIn(type, byte.class, Byte.class)) { - FieldUtils.writeStaticField(field, afterValue = Byte.valueOf(optionValue)); + afterValue = Byte.valueOf(optionValue); } else if (isIn(type, short.class, Short.class)) { - FieldUtils.writeStaticField(field, afterValue = Short.valueOf(optionValue)); + afterValue = Short.valueOf(optionValue); } else if (isIn(type, short.class, String.class)) { - FieldUtils.writeStaticField(field, afterValue = optionValue); + afterValue = optionValue; } else { 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())); } + String validateError = validateOptionValue(optionAnnotation.name(), afterValue); + if (validateError != null) { + return ExitStatus.failure(-1, validateError); + } + + FieldUtils.writeStaticField(field, afterValue); + + // FIXME hack for ongl strict + if (field.getName().equals("strict")) { + GlobalOptions.updateOnglStrict(Boolean.valueOf(optionValue)); + logger.info("update ongl strict to: {}", optionValue); + } + ChangeResultVO changeResultVO = new ChangeResultVO(optionAnnotation.name(), beforeValue, afterValue); process.appendResult(new OptionsModel(changeResultVO)); return ExitStatus.success(); } + static String validateOptionValue(String optionName, Object optionValue) { + if ("object-size-limit".equals(optionName) + && optionValue instanceof Integer + && ((Integer) optionValue).intValue() <= 0) { + return "options[object-size-limit] must be greater than 0."; + } + return null; + } + /** * 判断当前动作是否需要展示整个options diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java index 2a207dcdc..da7c7909a 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelCommand.java @@ -68,7 +68,7 @@ public class TimeTunnelCommand extends EnhancerCommand { // expand of TimeTunnel private Integer expand = 1; // upper size limit - private Integer sizeLimit = 10 * 1024 * 1024; + private Integer sizeLimit; // watch the index TimeTunnel private String watchExpress = com.taobao.arthas.core.util.Constants.EMPTY_STRING; private String searchExpress = com.taobao.arthas.core.util.Constants.EMPTY_STRING; @@ -131,7 +131,7 @@ public class TimeTunnelCommand extends EnhancerCommand { } @Option(shortName = "M", longName = "sizeLimit") - @Description("Upper size limit in bytes for the result (10 * 1024 * 1024 by default)") + @Description("Upper size limit in bytes for the result (must be greater than 0, default value comes from options object-size-limit)") public void setSizeLimit(Integer sizeLimit) { this.sizeLimit = sizeLimit; } @@ -234,10 +234,22 @@ public class TimeTunnelCommand extends EnhancerCommand { return !StringUtils.isEmpty(searchExpress); } + static String validateSizeLimit(Integer sizeLimit) { + if (sizeLimit != null && sizeLimit.intValue() <= 0) { + return "sizeLimit must be greater than 0."; + } + return null; + } + /** * 检查参数是否合法 */ private void checkArguments() { + String validateError = validateSizeLimit(sizeLimit); + if (validateError != null) { + throw new IllegalArgumentException(validateError); + } + // 检查d/p参数是否有i参数配套 if ((isDelete || isPlay) && null == index) { throw new IllegalArgumentException("Time fragment index is expected, please type -i to specify"); diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java index 041e8a39c..c7f26fdbb 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java @@ -43,7 +43,7 @@ public class WatchCommand extends EnhancerCommand { private boolean isException = false; private boolean isSuccess = false; private Integer expand = 1; - private Integer sizeLimit = 10 * 1024 * 1024; + private Integer sizeLimit; private boolean isRegEx = false; private int numberOfLimit = 100; @@ -97,7 +97,7 @@ public class WatchCommand extends EnhancerCommand { } @Option(shortName = "M", longName = "sizeLimit") - @Description("Upper size limit in bytes for the result (10 * 1024 * 1024 by default)") + @Description("Upper size limit in bytes for the result (must be greater than 0, default value comes from options object-size-limit)") public void setSizeLimit(Integer sizeLimit) { this.sizeLimit = sizeLimit; } @@ -199,6 +199,16 @@ public class WatchCommand extends EnhancerCommand { return methodNameMatcher; } + @Override + public void process(CommandProcess process) { + String validateError = validateSizeLimit(sizeLimit); + if (validateError != null) { + process.end(-1, validateError); + return; + } + super.process(process); + } + @Override protected AdviceListener getAdviceListener(CommandProcess process) { return new WatchAdviceListener(this, process, GlobalOptions.verbose || this.verbose); @@ -208,4 +218,11 @@ public class WatchCommand extends EnhancerCommand { protected void completeArgument3(Completion completion) { CompletionUtils.complete(completion, Arrays.asList(EXPRESS_EXAMPLES)); } + + static String validateSizeLimit(Integer sizeLimit) { + if (sizeLimit != null && sizeLimit.intValue() <= 0) { + return "sizeLimit must be greater than 0."; + } + return null; + } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/TimeTunnelView.java b/core/src/main/java/com/taobao/arthas/core/command/view/TimeTunnelView.java index 12922ed46..a37fd595c 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/TimeTunnelView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/TimeTunnelView.java @@ -22,7 +22,7 @@ public class TimeTunnelView extends ResultView { @Override public void draw(CommandProcess process, TimeTunnelModel timeTunnelModel) { - Integer sizeLimit = timeTunnelModel.getSizeLimit(); + int sizeLimitValue = ObjectView.normalizeMaxObjectLength(timeTunnelModel.getSizeLimit()); if (timeTunnelModel.getTimeFragmentList() != null) { //show list table: tt -l / tt -t @@ -35,7 +35,7 @@ public class TimeTunnelView extends ResultView { TableElement table = TimeTunnelTable.createDefaultTable(); TimeTunnelTable.drawTimeTunnel(table, tf); TimeTunnelTable.drawParameters(table, tf.getParams()); - TimeTunnelTable.drawReturnObj(table, tf, sizeLimit); + TimeTunnelTable.drawReturnObj(table, tf, sizeLimitValue); TimeTunnelTable.drawThrowException(table, tf); process.write(RenderUtil.render(table, process.width())); @@ -43,7 +43,7 @@ public class TimeTunnelView extends ResultView { //watch single TimeFragment: tt -i 1000 -w 'params' ObjectVO valueVO = timeTunnelModel.getWatchValue(); if (valueVO.needExpand()) { - process.write(new ObjectView(sizeLimit, valueVO).draw()).write("\n"); + process.write(new ObjectView(sizeLimitValue, valueVO).draw()).write("\n"); } else { process.write(StringUtils.objectToString(valueVO.getObject())).write("\n"); } @@ -52,7 +52,7 @@ public class TimeTunnelView extends ResultView { //search & watch: tt -s 'returnObj!=null' -w 'returnObj' TableElement table = TimeTunnelTable.createDefaultTable(); TimeTunnelTable.drawWatchTableHeader(table); - TimeTunnelTable.drawWatchResults(table, timeTunnelModel.getWatchResults(), sizeLimit); + TimeTunnelTable.drawWatchResults(table, timeTunnelModel.getWatchResults(), sizeLimitValue); process.write(RenderUtil.render(table, process.width())); } else if (timeTunnelModel.getReplayResult() != null) { @@ -63,7 +63,7 @@ public class TimeTunnelView extends ResultView { TimeTunnelTable.drawPlayHeader(replayResult.getClassName(), replayResult.getMethodName(), replayResult.getObject(), replayResult.getIndex(), table); TimeTunnelTable.drawParameters(table, replayResult.getParams()); if (replayResult.isReturn()) { - TimeTunnelTable.drawPlayResult(table, replayResult.getReturnObj(), sizeLimit, replayResult.getCost()); + TimeTunnelTable.drawPlayResult(table, replayResult.getReturnObj(), sizeLimitValue, replayResult.getCost()); } else { TimeTunnelTable.drawPlayException(table, replayResult.getThrowExp()); } diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/WatchView.java b/core/src/main/java/com/taobao/arthas/core/command/view/WatchView.java index b88644dac..c16996077 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/WatchView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/WatchView.java @@ -17,8 +17,9 @@ public class WatchView extends ResultView { @Override public void draw(CommandProcess process, WatchModel model) { ObjectVO objectVO = model.getValue(); + int sizeLimit = ObjectView.normalizeMaxObjectLength(model.getSizeLimit()); String result = StringUtils.objectToString( - objectVO.needExpand() ? new ObjectView(model.getSizeLimit(), objectVO).draw() : objectVO.getObject()); + objectVO.needExpand() ? new ObjectView(sizeLimit, objectVO).draw() : objectVO.getObject()); StringBuilder sb = new StringBuilder(); sb.append("method=").append(model.getClassName()).append(".").append(model.getMethodName()) diff --git a/core/src/main/java/com/taobao/arthas/core/view/ObjectView.java b/core/src/main/java/com/taobao/arthas/core/view/ObjectView.java index 5e7d1ebbe..232b11b47 100644 --- a/core/src/main/java/com/taobao/arthas/core/view/ObjectView.java +++ b/core/src/main/java/com/taobao/arthas/core/view/ObjectView.java @@ -27,7 +27,6 @@ import static java.lang.String.format; public class ObjectView implements View { public static final int MAX_DEEP = 4; private static final Logger logger = LoggerFactory.getLogger(ObjectView.class); - private final static int MAX_OBJECT_LENGTH = ArthasConstants.MAX_HTTP_CONTENT_LENGTH; private static final ObjectWriterProvider JSON_OBJECT_WRITER_PROVIDER = new ObjectWriterProvider( new ObjectWriterCreator() { @Override @@ -53,7 +52,7 @@ public class ObjectView implements View { private final int maxObjectLength; public ObjectView(ObjectVO objectVO) { - this(MAX_OBJECT_LENGTH, objectVO); + this(defaultMaxObjectLength(), objectVO); } // int参数在前面,防止构造函数二义性 @@ -62,7 +61,7 @@ public class ObjectView implements View { } public ObjectView(Object object, int deep) { - this(object, deep, MAX_OBJECT_LENGTH); + this(object, deep, defaultMaxObjectLength()); } public ObjectView(Object object, int deep, int maxObjectLength) { @@ -83,7 +82,7 @@ public class ObjectView implements View { } catch (ObjectTooLargeException e) { buf.append(" Object size exceeds size limit: ") .append(maxObjectLength) - .append(", try to specify -M size_limit in your command, check the help command for more."); + .append(", try to use `options object-size-limit ` to increase the limit."); return buf.toString(); } catch (Throwable t) { logger.error("ObjectView draw error, object class: {}", object.getClass(), t); @@ -699,5 +698,19 @@ public class ObjectView implements View { } } + public static int normalizeMaxObjectLength(Integer limit) { + if (limit != null && limit > 0) { + return limit; + } + int globalLimit = GlobalOptions.objectSizeLimit; + if (globalLimit > 0) { + return globalLimit; + } + return ArthasConstants.MAX_HTTP_CONTENT_LENGTH; + } + + private static int defaultMaxObjectLength() { + return normalizeMaxObjectLength(null); + } } diff --git a/core/src/test/java/com/taobao/arthas/core/command/basic1000/OptionsCommandTest.java b/core/src/test/java/com/taobao/arthas/core/command/basic1000/OptionsCommandTest.java new file mode 100644 index 000000000..c401636ca --- /dev/null +++ b/core/src/test/java/com/taobao/arthas/core/command/basic1000/OptionsCommandTest.java @@ -0,0 +1,17 @@ +package com.taobao.arthas.core.command.basic1000; + +import org.junit.Assert; +import org.junit.Test; + +public class OptionsCommandTest { + + @Test + public void testValidateObjectSizeLimitOptionValue() { + Assert.assertEquals("options[object-size-limit] must be greater than 0.", + OptionsCommand.validateOptionValue("object-size-limit", Integer.valueOf(0))); + Assert.assertEquals("options[object-size-limit] must be greater than 0.", + OptionsCommand.validateOptionValue("object-size-limit", Integer.valueOf(-1))); + Assert.assertNull(OptionsCommand.validateOptionValue("object-size-limit", Integer.valueOf(1))); + Assert.assertNull(OptionsCommand.validateOptionValue("json-format", Boolean.TRUE)); + } +} diff --git a/core/src/test/java/com/taobao/arthas/core/command/monitor200/SizeLimitValidationTest.java b/core/src/test/java/com/taobao/arthas/core/command/monitor200/SizeLimitValidationTest.java new file mode 100644 index 000000000..af458dd06 --- /dev/null +++ b/core/src/test/java/com/taobao/arthas/core/command/monitor200/SizeLimitValidationTest.java @@ -0,0 +1,23 @@ +package com.taobao.arthas.core.command.monitor200; + +import org.junit.Assert; +import org.junit.Test; + +public class SizeLimitValidationTest { + + @Test + public void testWatchSizeLimitValidation() { + Assert.assertEquals("sizeLimit must be greater than 0.", WatchCommand.validateSizeLimit(Integer.valueOf(0))); + Assert.assertEquals("sizeLimit must be greater than 0.", WatchCommand.validateSizeLimit(Integer.valueOf(-1))); + Assert.assertNull(WatchCommand.validateSizeLimit(Integer.valueOf(1))); + Assert.assertNull(WatchCommand.validateSizeLimit(null)); + } + + @Test + public void testTimeTunnelSizeLimitValidation() { + Assert.assertEquals("sizeLimit must be greater than 0.", TimeTunnelCommand.validateSizeLimit(Integer.valueOf(0))); + Assert.assertEquals("sizeLimit must be greater than 0.", TimeTunnelCommand.validateSizeLimit(Integer.valueOf(-1))); + Assert.assertNull(TimeTunnelCommand.validateSizeLimit(Integer.valueOf(1))); + Assert.assertNull(TimeTunnelCommand.validateSizeLimit(null)); + } +} diff --git a/core/src/test/java/com/taobao/arthas/core/view/ObjectViewTest.java b/core/src/test/java/com/taobao/arthas/core/view/ObjectViewTest.java index 5efb1008c..3c814a08b 100644 --- a/core/src/test/java/com/taobao/arthas/core/view/ObjectViewTest.java +++ b/core/src/test/java/com/taobao/arthas/core/view/ObjectViewTest.java @@ -1,5 +1,6 @@ package com.taobao.arthas.core.view; +import com.taobao.arthas.common.ArthasConstants; import com.taobao.arthas.core.GlobalOptions; import org.junit.Assert; import org.junit.Test; @@ -223,6 +224,37 @@ public class ObjectViewTest { } } + @Test + public void testDefaultSizeLimitFromGlobalOptions() { + int old = GlobalOptions.objectSizeLimit; + try { + GlobalOptions.objectSizeLimit = 5; + ObjectView objectView = new ObjectView("123456", 1); + String output = objectView.draw(); + Assert.assertTrue(output.contains("Object size exceeds size limit: 5")); + } finally { + GlobalOptions.objectSizeLimit = old; + } + } + + @Test + public void testNormalizeMaxObjectLength() { + int old = GlobalOptions.objectSizeLimit; + try { + GlobalOptions.objectSizeLimit = 9; + Assert.assertEquals(9, ObjectView.normalizeMaxObjectLength(null)); + Assert.assertEquals(9, ObjectView.normalizeMaxObjectLength(0)); + Assert.assertEquals(9, ObjectView.normalizeMaxObjectLength(-1)); + Assert.assertEquals(8, ObjectView.normalizeMaxObjectLength(8)); + + GlobalOptions.objectSizeLimit = 0; + Assert.assertEquals(ArthasConstants.MAX_HTTP_CONTENT_LENGTH, ObjectView.normalizeMaxObjectLength(null)); + Assert.assertEquals(ArthasConstants.MAX_HTTP_CONTENT_LENGTH, ObjectView.normalizeMaxObjectLength(-1)); + } finally { + GlobalOptions.objectSizeLimit = old; + } + } + @Test public void testDate() { Date d = new Date(1531204354961L - TimeZone.getDefault().getRawOffset() @@ -276,7 +308,7 @@ public class ObjectViewTest { " c1=@NestedClass[\n" + " code=@Integer[1],\n" + " c1=...\n" + - "... Object size exceeds size limit: 100, try to specify -M size_limit in your command, check the help command for more."; + "... Object size exceeds size limit: 100, try to use `options object-size-limit ` to increase the limit."; Assert.assertEquals(expected, objectView.draw()); } diff --git a/site/docs/doc/options.md b/site/docs/doc/options.md index 910ed7281..198881374 100644 --- a/site/docs/doc/options.md +++ b/site/docs/doc/options.md @@ -6,19 +6,20 @@ 全局开关 ::: -| 名称 | 默认值 | 描述 | -| ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| unsafe | false | 是否支持对系统级别的类进行增强,打开该开关可能导致把 JVM 搞挂,请慎重选择! | -| dump | false | 是否支持被增强了的类 dump 到外部文件中,如果打开开关,class 文件会被 dump 到`/${application working dir}/arthas-class-dump/`目录下,具体位置详见控制台输出 | -| batch-re-transform | true | 是否支持批量对匹配到的类执行 retransform 操作 | -| json-format | false | 是否支持 json 化的输出 | -| disable-sub-class | false | 是否禁用子类匹配,默认在匹配目标类的时候会默认匹配到其子类,如果想精确匹配,可以关闭此开关 | -| support-default-method | true | 是否支持匹配到 default method, 默认会查找 interface,匹配里面的 default method。参考 [#1105](https://github.com/alibaba/arthas/issues/1105) | -| save-result | false | 是否打开执行结果存日志功能,打开之后所有命令的运行结果都将保存到`~/logs/arthas-cache/result.log`中 | -| job-timeout | 1d | 异步后台任务的默认超时时间,超过这个时间,任务自动停止;比如设置 1d, 2h, 3m, 25s,分别代表天、小时、分、秒 | -| print-parent-fields | true | 是否打印在 parent class 里的 filed | -| verbose | false | 是否打印更多详细信息 | -| strict | true | 是否启用 strict 模式 | +| 名称 | 默认值 | 描述 | +| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| unsafe | false | 是否支持对系统级别的类进行增强,打开该开关可能导致把 JVM 搞挂,请慎重选择! | +| dump | false | 是否支持被增强了的类 dump 到外部文件中,如果打开开关,class 文件会被 dump 到`/${application working dir}/arthas-class-dump/`目录下,具体位置详见控制台输出 | +| batch-re-transform | true | 是否支持批量对匹配到的类执行 retransform 操作 | +| json-format | false | 是否支持 json 化的输出 | +| object-size-limit | 10485760 | ObjectView 输出大小上限(字节),必须大于 0,默认 `10 * 1024 * 1024` | +| disable-sub-class | false | 是否禁用子类匹配,默认在匹配目标类的时候会默认匹配到其子类,如果想精确匹配,可以关闭此开关 | +| support-default-method | true | 是否支持匹配到 default method, 默认会查找 interface,匹配里面的 default method。参考 [#1105](https://github.com/alibaba/arthas/issues/1105) | +| save-result | false | 是否打开执行结果存日志功能,打开之后所有命令的运行结果都将保存到`~/logs/arthas-cache/result.log`中 | +| job-timeout | 1d | 异步后台任务的默认超时时间,超过这个时间,任务自动停止;比如设置 1d, 2h, 3m, 25s,分别代表天、小时、分、秒 | +| print-parent-fields | true | 是否打印在 parent class 里的 filed | +| verbose | false | 是否打印更多详细信息 | +| strict | true | 是否启用 strict 模式 | ## 查看所有的 options @@ -40,6 +41,9 @@ $ options 2 boolea json-format false Option to support JS This option enables to format object outpu n ON format of object t with JSON when -x option selected. output + 1 int object-size- 10485760 Option to control O Upper size limit in bytes for ObjectView o + limit bjectView output utput, must be greater than 0. Default val + ue is 10 * 1024 * 1024. 1 boolea disable-sub- false Option to control in This option disable to include sub class w n class clude sub class when hen matching class. class matching diff --git a/site/docs/en/doc/options.md b/site/docs/en/doc/options.md index 59c380701..a7b14baac 100644 --- a/site/docs/en/doc/options.md +++ b/site/docs/en/doc/options.md @@ -12,6 +12,7 @@ Global options | dump | false | whether to dump enhanced class to the external files. If it's on, enhanced class will be dumped into `/${application dir}/arthas-class-dump/`, the specific output path will be output in the console | | batch-re-transform | true | whether to re-transform matched classes in batch | | json-format | false | whether to output in JSON format | +| object-size-limit | 10485760 | upper size limit in bytes for ObjectView output (must be greater than 0, default is `10 * 1024 * 1024`) | | disable-sub-class | false | whether to enable matching child classes. The default value is `true`. If exact match is desire, turn off this flag | | support-default-method | true | whether to enable matching default method in interface. The default value is `true`. Refer to [#1105](https://github.com/alibaba/arthas/issues/1105) | | save-result | false | whether to save execution result. All execution results will be saved to `~/logs/arthas-cache/result.log` when it's turned on | @@ -40,6 +41,9 @@ $ options 2 boolea json-format false Option to support JS This option enables to format object outpu n ON format of object t with JSON when -x option selected. output + 1 int object-size- 10485760 Option to control O Upper size limit in bytes for ObjectView o + limit bjectView output utput, must be greater than 0. Default val + ue is 10 * 1024 * 1024. 1 boolea disable-sub- false Option to control in This option disable to include sub class w n class clude sub class when hen matching class. class matching