diff --git a/core/src/main/java/com/taobao/arthas/core/command/klass100/ClassLoaderCommand.java b/core/src/main/java/com/taobao/arthas/core/command/klass100/ClassLoaderCommand.java index 1cb86775b..757829198 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/klass100/ClassLoaderCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/klass100/ClassLoaderCommand.java @@ -293,7 +293,7 @@ public class ClassLoaderCommand extends AnnotatedCommand { try { Class clazz = targetClassLoader.loadClass(this.loadClass); process.appendResult(new MessageModel("load class success.")); - ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, false); + ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, false, null); process.appendResult(new ClassLoaderModel().setLoadClass(classInfo)); } catch (Throwable e) { diff --git a/core/src/main/java/com/taobao/arthas/core/command/klass100/OgnlCommand.java b/core/src/main/java/com/taobao/arthas/core/command/klass100/OgnlCommand.java index 1d9ac6958..bb36bb5d9 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/klass100/OgnlCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/klass100/OgnlCommand.java @@ -11,6 +11,7 @@ import com.taobao.arthas.core.command.express.Express; import com.taobao.arthas.core.command.express.ExpressException; import com.taobao.arthas.core.command.express.ExpressFactory; import com.taobao.arthas.core.command.model.ClassLoaderVO; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.OgnlModel; import com.taobao.arthas.core.shell.command.AnnotatedCommand; import com.taobao.arthas.core.shell.command.CommandProcess; @@ -103,8 +104,7 @@ public class OgnlCommand extends AnnotatedCommand { try { Object value = unpooledExpress.get(express); OgnlModel ognlModel = new OgnlModel() - .setValue(value) - .setExpand(expand); + .setValue(new ObjectVO(value, expand)); process.appendResult(ognlModel); process.end(); } catch (ExpressException e) { diff --git a/core/src/main/java/com/taobao/arthas/core/command/klass100/SearchClassCommand.java b/core/src/main/java/com/taobao/arthas/core/command/klass100/SearchClassCommand.java index 1fa1e57f4..0eaf1d28e 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/klass100/SearchClassCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/klass100/SearchClassCommand.java @@ -140,8 +140,8 @@ public class SearchClassCommand extends AnnotatedCommand { return; } for (Class clazz : matchedClasses) { - ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, isField); - process.appendResult(new SearchClassModel(classInfo, isDetail, isField, expand)); + ClassDetailVO classInfo = ClassUtils.createClassInfo(clazz, isField, expand); + process.appendResult(new SearchClassModel(classInfo, isDetail, isField)); } } else { int pageSize = 256; diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/FieldVO.java b/core/src/main/java/com/taobao/arthas/core/command/model/FieldVO.java index 79615ff4d..9580fa2ec 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/FieldVO.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/FieldVO.java @@ -8,7 +8,7 @@ public class FieldVO { private String type; private String modifier; private String[] annotations; - private Object value; + private ObjectVO value; private boolean isStatic; public String getName() { @@ -35,11 +35,11 @@ public class FieldVO { this.modifier = modifier; } - public Object getValue() { + public ObjectVO getValue() { return value; } - public void setValue(Object value) { + public void setValue(ObjectVO value) { this.value = value; } @@ -58,4 +58,5 @@ public class FieldVO { public void setStatic(boolean aStatic) { isStatic = aStatic; } + } diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/GetStaticModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/GetStaticModel.java index 0aa150f11..fe24794b0 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/GetStaticModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/GetStaticModel.java @@ -9,8 +9,8 @@ import java.util.Collection; public class GetStaticModel extends ResultModel { private Collection matchedClasses; + private String fieldName; private ObjectVO field; - private int expand; private Collection matchedClassLoaders; private String classLoaderClass; @@ -18,8 +18,8 @@ public class GetStaticModel extends ResultModel { } public GetStaticModel(String fieldName, Object fieldValue, int expand) { - this.field = new ObjectVO(fieldName, fieldValue); - this.expand = expand; + this.fieldName = fieldName; + this.field = new ObjectVO(fieldValue, expand); } public GetStaticModel(Collection matchedClasses) { @@ -34,20 +34,20 @@ public class GetStaticModel extends ResultModel { this.field = field; } - public Collection getMatchedClasses() { - return matchedClasses; + public String getFieldName() { + return fieldName; } - public void setMatchedClasses(Collection matchedClasses) { - this.matchedClasses = matchedClasses; + public void setFieldName(String fieldName) { + this.fieldName = fieldName; } - public int getExpand() { - return expand; + public Collection getMatchedClasses() { + return matchedClasses; } - public void setExpand(int expand) { - this.expand = expand; + public void setMatchedClasses(Collection matchedClasses) { + this.matchedClasses = matchedClasses; } public String getClassLoaderClass() { diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/ObjectVO.java b/core/src/main/java/com/taobao/arthas/core/command/model/ObjectVO.java index 621857f67..b74c513c4 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/ObjectVO.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/ObjectVO.java @@ -1,34 +1,55 @@ package com.taobao.arthas.core.command.model; /** - * @author gongdewei 2020/4/29 + *
+ * 包装一层,解决json输出问题
+ * https://github.com/alibaba/arthas/issues/2261
+ * 
+ * + * @author hengyunabc 2022-08-24 + * */ public class ObjectVO { - private String name; - private Object value; + private Object object; + private Integer expand; - public ObjectVO(String name, Object value) { - this.name = name; - this.value = value; + public ObjectVO(Object object, Integer expand) { + this.object = object; + this.expand = expand; } - public ObjectVO(Object value) { - this.value = value; + public static ObjectVO[] array(Object[] objects, Integer expand) { + ObjectVO[] result = new ObjectVO[objects.length]; + for (int i = 0; i < objects.length; ++i) { + result[i] = new ObjectVO(objects[i], expand); + } + return result; } - public String getName() { - return name; + public int expandOrDefault() { + if (expand != null) { + return expand; + } + return 1; } - public void setName(String name) { - this.name = name; + public boolean needExpand() { + return null != expand && expand > 0; } - public Object getValue() { - return value; + public Object getObject() { + return object; } - public void setValue(Object value) { - this.value = value; + public void setObject(Object object) { + this.object = object; + } + + public Integer getExpand() { + return expand; + } + + public void setExpand(Integer expand) { + this.expand = expand; } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/OgnlModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/OgnlModel.java index 50cdbc4b3..0a6c8f953 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/OgnlModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/OgnlModel.java @@ -7,8 +7,7 @@ import java.util.Collection; * @author gongdewei 2020/4/29 */ public class OgnlModel extends ResultModel { - private Object value; - private int expand = 1; + private ObjectVO value; private Collection matchedClassLoaders; private String classLoaderClass; @@ -19,24 +18,15 @@ public class OgnlModel extends ResultModel { return "ognl"; } - public Object getValue() { + public ObjectVO getValue() { return value; } - public OgnlModel setValue(Object value) { + public OgnlModel setValue(ObjectVO value) { this.value = value; return this; } - public int getExpand() { - return expand; - } - - public OgnlModel setExpand(int expand) { - this.expand = expand; - return this; - } - public String getClassLoaderClass() { return classLoaderClass; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/SearchClassModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/SearchClassModel.java index fcf7c23fa..3f7015837 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/SearchClassModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/SearchClassModel.java @@ -11,7 +11,6 @@ public class SearchClassModel extends ResultModel { private ClassDetailVO classInfo; private boolean withField; private boolean detailed; - private Integer expand; private List classNames; private int segment; @@ -21,11 +20,10 @@ public class SearchClassModel extends ResultModel { public SearchClassModel() { } - public SearchClassModel(ClassDetailVO classInfo, boolean detailed, boolean withField, Integer expand) { + public SearchClassModel(ClassDetailVO classInfo, boolean detailed, boolean withField) { this.classInfo = classInfo; this.detailed = detailed; this.withField = withField; - this.expand = expand; } public SearchClassModel(List classNames, int segment) { @@ -70,10 +68,6 @@ public class SearchClassModel extends ResultModel { return withField; } - public Integer getExpand() { - return expand; - } - public String getClassLoaderClass() { return classLoaderClass; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/TimeFragmentVO.java b/core/src/main/java/com/taobao/arthas/core/command/model/TimeFragmentVO.java index 591b9f1cc..d6bd3a47b 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/TimeFragmentVO.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/TimeFragmentVO.java @@ -15,9 +15,9 @@ public class TimeFragmentVO { private String object; private String className; private String methodName; - private Object[] params; - private Object returnObj; - private Throwable throwExp; + private ObjectVO[] params; + private ObjectVO returnObj; + private ObjectVO throwExp; public TimeFragmentVO() { } @@ -94,29 +94,29 @@ public class TimeFragmentVO { return this; } - public Object[] getParams() { + public ObjectVO[] getParams() { return params; } - public TimeFragmentVO setParams(Object[] params) { + public TimeFragmentVO setParams(ObjectVO[] params) { this.params = params; return this; } - public Object getReturnObj() { + public ObjectVO getReturnObj() { return returnObj; } - public TimeFragmentVO setReturnObj(Object returnObj) { + public TimeFragmentVO setReturnObj(ObjectVO returnObj) { this.returnObj = returnObj; return this; } - public Throwable getThrowExp() { + public ObjectVO getThrowExp() { return throwExp; } - public TimeFragmentVO setThrowExp(Throwable throwExp) { + public TimeFragmentVO setThrowExp(ObjectVO throwExp) { this.throwExp = throwExp; return this; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/TimeTunnelModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/TimeTunnelModel.java index f6b9c1c5b..7b5cfdd4f 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/TimeTunnelModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/TimeTunnelModel.java @@ -24,10 +24,10 @@ public class TimeTunnelModel extends ResultModel { //重放执行的次数 private Integer replayNo; - private Object watchValue; + private ObjectVO watchValue; //search: tt -s {} -w {} - private Map watchResults; + private Map watchResults; private Integer expand; @@ -75,20 +75,20 @@ public class TimeTunnelModel extends ResultModel { return this; } - public Object getWatchValue() { + public ObjectVO getWatchValue() { return watchValue; } - public TimeTunnelModel setWatchValue(Object watchValue) { + public TimeTunnelModel setWatchValue(ObjectVO watchValue) { this.watchValue = watchValue; return this; } - public Map getWatchResults() { + public Map getWatchResults() { return watchResults; } - public TimeTunnelModel setWatchResults(Map watchResults) { + public TimeTunnelModel setWatchResults(Map watchResults) { this.watchResults = watchResults; return this; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/VmToolModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/VmToolModel.java index ae73a635e..d8364f4f0 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/VmToolModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/VmToolModel.java @@ -8,8 +8,7 @@ import java.util.Collection; * */ public class VmToolModel extends ResultModel { - private Object value; - private int expand = 1; + private ObjectVO value; private Collection matchedClassLoaders; private String classLoaderClass; @@ -20,24 +19,15 @@ public class VmToolModel extends ResultModel { return "vmtool"; } - public Object getValue() { + public ObjectVO getValue() { return value; } - public VmToolModel setValue(Object value) { + public VmToolModel setValue(ObjectVO value) { this.value = value; return this; } - public int getExpand() { - return expand; - } - - public VmToolModel setExpand(int expand) { - this.expand = expand; - return this; - } - public String getClassLoaderClass() { return classLoaderClass; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/WatchModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/WatchModel.java index 200518b3f..e05c090c7 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/WatchModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/WatchModel.java @@ -11,9 +11,8 @@ public class WatchModel extends ResultModel { private Date ts; private double cost; - private Object value; + private ObjectVO value; - private Integer expand; private Integer sizeLimit; private String className; private String methodName; @@ -39,7 +38,7 @@ public class WatchModel extends ResultModel { return cost; } - public Object getValue() { + public ObjectVO getValue() { return value; } @@ -47,22 +46,14 @@ public class WatchModel extends ResultModel { this.cost = cost; } - public void setValue(Object value) { + public void setValue(ObjectVO value) { this.value = value; } - public void setExpand(Integer expand) { - this.expand = expand; - } - public void setSizeLimit(Integer sizeLimit) { this.sizeLimit = sizeLimit; } - public Integer getExpand() { - return expand; - } - public Integer getSizeLimit() { return sizeLimit; } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelAdviceListener.java index 15f5fb255..a422dbbf1 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelAdviceListener.java @@ -88,7 +88,7 @@ public class TimeTunnelAdviceListener extends AdviceListenerAdapter { int index = command.putTimeTunnel(timeTunnel); - TimeFragmentVO timeFragmentVO = TimeTunnelCommand.createTimeFragmentVO(index, timeTunnel); + TimeFragmentVO timeFragmentVO = TimeTunnelCommand.createTimeFragmentVO(index, timeTunnel, command.getExpand()); TimeTunnelModel timeTunnelModel = new TimeTunnelModel() .setTimeFragmentList(Collections.singletonList(timeFragmentVO)) .setFirst(isFirst); 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 9a499648b..ce120ec58 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 @@ -10,6 +10,7 @@ import com.taobao.arthas.core.command.Constants; import com.taobao.arthas.core.command.express.ExpressException; import com.taobao.arthas.core.command.express.ExpressFactory; import com.taobao.arthas.core.command.model.MessageModel; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.RowAffectModel; import com.taobao.arthas.core.command.model.TimeFragmentVO; import com.taobao.arthas.core.command.model.TimeTunnelModel; @@ -214,7 +215,6 @@ public class TimeTunnelCommand extends EnhancerCommand { return numberOfLimit; } - public int getReplayTimes() { return replayTimes; } @@ -223,6 +223,10 @@ public class TimeTunnelCommand extends EnhancerCommand { return replayInterval; } + public Integer getExpand() { + return expand; + } + private boolean hasWatchExpress() { return !StringUtils.isEmpty(watchExpress); } @@ -336,7 +340,7 @@ public class TimeTunnelCommand extends EnhancerCommand { return; } - TimeFragmentVO timeFragmentVO = createTimeFragmentVO(index, tf); + TimeFragmentVO timeFragmentVO = createTimeFragmentVO(index, tf, expand); TimeTunnelModel timeTunnelModel = new TimeTunnelModel() .setTimeFragment(timeFragmentVO) .setExpand(expand) @@ -365,7 +369,7 @@ public class TimeTunnelCommand extends EnhancerCommand { Object value = ExpressFactory.unpooledExpress(advice.getLoader()).bind(advice).get(watchExpress); TimeTunnelModel timeTunnelModel = new TimeTunnelModel() - .setWatchValue(value) + .setWatchValue(new ObjectVO(value, expand)) .setExpand(expand) .setSizeLimit(sizeLimit); process.appendResult(timeTunnelModel); @@ -398,10 +402,10 @@ public class TimeTunnelCommand extends EnhancerCommand { if (hasWatchExpress()) { // 执行watchExpress - Map searchResults = new LinkedHashMap(); + Map searchResults = new LinkedHashMap(); for (Map.Entry entry : matchingTimeSegmentMap.entrySet()) { Object value = ExpressFactory.threadLocalExpress(entry.getValue().getAdvice()).get(watchExpress); - searchResults.put(entry.getKey(), value); + searchResults.put(entry.getKey(), new ObjectVO(value, expand)); } TimeTunnelModel timeTunnelModel = new TimeTunnelModel() @@ -456,12 +460,12 @@ public class TimeTunnelCommand extends EnhancerCommand { private List createTimeTunnelVOList(Map timeFragmentMap) { List timeFragmentList = new ArrayList(timeFragmentMap.size()); for (Map.Entry entry : timeFragmentMap.entrySet()) { - timeFragmentList.add(createTimeFragmentVO(entry.getKey(), entry.getValue())); + timeFragmentList.add(createTimeFragmentVO(entry.getKey(), entry.getValue(), expand)); } return timeFragmentList; } - public static TimeFragmentVO createTimeFragmentVO(Integer index, TimeFragment tf) { + public static TimeFragmentVO createTimeFragmentVO(Integer index, TimeFragment tf, Integer expand) { Advice advice = tf.getAdvice(); String object = advice.getTarget() == null ? "NULL" @@ -471,11 +475,11 @@ public class TimeTunnelCommand extends EnhancerCommand { .setIndex(index) .setTimestamp(tf.getGmtCreate()) .setCost(tf.getCost()) - .setParams(advice.getParams()) + .setParams(ObjectVO.array(advice.getParams(), expand)) .setReturn(advice.isAfterReturning()) - .setReturnObj(advice.getReturnObj()) + .setReturnObj(new ObjectVO(advice.getReturnObj(), expand)) .setThrow(advice.isAfterThrowing()) - .setThrowExp(advice.getThrowExp()) + .setThrowExp(new ObjectVO(advice.getThrowExp(), expand)) .setObject(object) .setClassName(advice.getClazz().getName()) .setMethodName(advice.getMethod().getName()); @@ -508,7 +512,7 @@ public class TimeTunnelCommand extends EnhancerCommand { long beginTime = System.nanoTime(); //copy from tt record - TimeFragmentVO replayResult = createTimeFragmentVO(index, tf); + TimeFragmentVO replayResult = createTimeFragmentVO(index, tf, expand); replayResult.setTimestamp(new Date()) .setCost(0) .setReturn(false) @@ -522,13 +526,13 @@ public class TimeTunnelCommand extends EnhancerCommand { double cost = (System.nanoTime() - beginTime) / 1000000.0; replayResult.setCost(cost) .setReturn(true) - .setReturnObj(returnObj); + .setReturnObj(new ObjectVO(returnObj, expand)); } catch (Throwable t) { //throw exp double cost = (System.nanoTime() - beginTime) / 1000000.0; replayResult.setCost(cost) .setThrow(true) - .setThrowExp(t); + .setThrowExp(new ObjectVO(t, expand)); } TimeTunnelModel timeTunnelModel = new TimeTunnelModel() diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelTable.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelTable.java index 3b38a6af7..348daa5ac 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelTable.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/TimeTunnelTable.java @@ -1,5 +1,6 @@ package com.taobao.arthas.core.command.monitor200; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.TimeFragmentVO; import com.taobao.arthas.core.util.StringUtils; import com.taobao.arthas.core.view.ObjectView; @@ -102,17 +103,17 @@ public class TimeTunnelTable { .row("IS-EXCEPTION", "" + tf.isThrow()); } - public static void drawThrowException(TableElement table, TimeFragmentVO tf, boolean isNeedExpand, Integer expandLevel) { + public static void drawThrowException(TableElement table, TimeFragmentVO tf) { if (tf.isThrow()) { //noinspection ThrowableResultOfMethodCallIgnored - Throwable throwable = tf.getThrowExp(); - if (isNeedExpand) { - table.row("THROW-EXCEPTION", new ObjectView(throwable, expandLevel).draw()); + ObjectVO throwableVO = tf.getThrowExp(); + if (throwableVO.needExpand()) { + table.row("THROW-EXCEPTION", new ObjectView(throwableVO).draw()); } else { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); try { - throwable.printStackTrace(printWriter); + ((Throwable) throwableVO.getObject()).printStackTrace(printWriter); table.row("THROW-EXCEPTION", stringWriter.toString()); } finally { printWriter.close(); @@ -121,22 +122,22 @@ public class TimeTunnelTable { } } - public static void drawReturnObj(TableElement table, TimeFragmentVO tf, boolean isNeedExpand, Integer expandLevel, Integer sizeLimit) { + public static void drawReturnObj(TableElement table, TimeFragmentVO tf, Integer sizeLimit) { if (tf.isReturn()) { - if (isNeedExpand) { - table.row("RETURN-OBJ", new ObjectView(tf.getReturnObj(), expandLevel, sizeLimit).draw()); + if (tf.getReturnObj().needExpand()) { + table.row("RETURN-OBJ", new ObjectView(sizeLimit, tf.getReturnObj()).draw()); } else { table.row("RETURN-OBJ", "" + StringUtils.objectToString(tf.getReturnObj())); } } } - public static void drawParameters(TableElement table, Object[] params, boolean isNeedExpand, Integer expandLevel) { + public static void drawParameters(TableElement table, ObjectVO[] params) { if (params != null) { int paramIndex = 0; - for (Object param : params) { - if (isNeedExpand) { - table.row("PARAMETERS[" + paramIndex++ + "]", new ObjectView(param, expandLevel).draw()); + for (ObjectVO param : params) { + if (param.needExpand()) { + table.row("PARAMETERS[" + paramIndex++ + "]", new ObjectView(param).draw()); } else { table.row("PARAMETERS[" + paramIndex++ + "]", "" + StringUtils.objectToString(param)); } @@ -149,12 +150,11 @@ public class TimeTunnelTable { .style(Decoration.bold.bold())); } - public static void drawWatchResults(TableElement table, Map watchResults, boolean isNeedExpand, - Integer expandLevel, Integer sizeLimit) { - for (Map.Entry entry : watchResults.entrySet()) { - Object value = entry.getValue(); + public static void drawWatchResults(TableElement table, Map watchResults, Integer sizeLimit) { + for (Map.Entry entry : watchResults.entrySet()) { + ObjectVO objectVO = entry.getValue(); table.row("" + entry.getKey(), "" + - (isNeedExpand ? new ObjectView(value, expandLevel, sizeLimit).draw() : StringUtils.objectToString(value))); + (objectVO.needExpand() ? new ObjectView(sizeLimit, objectVO).draw() : StringUtils.objectToString(objectVO.getObject()))); } } @@ -168,7 +168,7 @@ public class TimeTunnelTable { .row("METHOD", methodName); } - public static void drawPlayResult(TableElement table, Object returnObj, boolean isNeedExpand, int expandLevel, + public static void drawPlayResult(TableElement table, ObjectVO returnObjVO, int sizeLimit, double cost) { // 执行成功:输出成功状态 table.row("IS-RETURN", "" + true); @@ -176,28 +176,29 @@ public class TimeTunnelTable { table.row("COST(ms)", "" + cost); // 执行成功:输出成功结果 - if (isNeedExpand) { - table.row("RETURN-OBJ", new ObjectView(returnObj, expandLevel, sizeLimit).draw()); + if (returnObjVO.needExpand()) { + table.row("RETURN-OBJ", new ObjectView(sizeLimit, returnObjVO).draw()); } else { - table.row("RETURN-OBJ", "" + StringUtils.objectToString(returnObj)); + table.row("RETURN-OBJ", "" + StringUtils.objectToString(returnObjVO.getObject())); } } - public static void drawPlayException(TableElement table, Throwable t, boolean isNeedExpand, int expandLevel) { + public static void drawPlayException(TableElement table, ObjectVO throwableVO) { // 执行失败:输出失败状态 table.row("IS-RETURN", "" + false); table.row("IS-EXCEPTION", "" + true); // 执行失败:输出失败异常信息 Throwable cause; + Throwable t = (Throwable) throwableVO.getObject(); if (t instanceof InvocationTargetException) { cause = t.getCause(); } else { cause = t; } - if (isNeedExpand) { - table.row("THROW-EXCEPTION", new ObjectView(cause, expandLevel).draw()); + if (throwableVO.needExpand()) { + table.row("THROW-EXCEPTION", new ObjectView(cause, throwableVO.expandOrDefault()).draw()); } else { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java index 83fa5ea38..749785c58 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java @@ -20,7 +20,7 @@ import com.taobao.arthas.core.command.express.Express; import com.taobao.arthas.core.command.express.ExpressException; import com.taobao.arthas.core.command.express.ExpressFactory; import com.taobao.arthas.core.command.model.ClassLoaderVO; -import com.taobao.arthas.core.command.model.SearchClassModel; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.VmToolModel; import com.taobao.arthas.core.shell.cli.Completion; import com.taobao.arthas.core.shell.cli.CompletionUtils; @@ -30,7 +30,6 @@ import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.ClassLoaderUtils; import com.taobao.arthas.core.util.ClassUtils; import com.taobao.arthas.core.util.SearchUtils; -import com.taobao.arthas.core.view.ObjectView; import com.taobao.middleware.cli.annotations.DefaultValue; import com.taobao.middleware.cli.annotations.Description; import com.taobao.middleware.cli.annotations.Name; @@ -218,7 +217,7 @@ public class VmToolCommand extends AnnotatedCommand { } } - VmToolModel vmToolModel = new VmToolModel().setValue(value).setExpand(expand); + VmToolModel vmToolModel = new VmToolModel().setValue(new ObjectVO(value, expand)); process.appendResult(vmToolModel); process.end(); } diff --git a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java index 691e2ec0c..7d9175f98 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java +++ b/core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java @@ -6,6 +6,7 @@ import com.taobao.arthas.core.advisor.AccessPoint; import com.taobao.arthas.core.advisor.Advice; import com.taobao.arthas.core.advisor.AdviceListenerAdapter; import com.taobao.arthas.core.advisor.ArthasMethod; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.WatchModel; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.LogUtil; @@ -88,8 +89,7 @@ class WatchAdviceListener extends AdviceListenerAdapter { WatchModel model = new WatchModel(); model.setTs(new Date()); model.setCost(cost); - model.setValue(value); - model.setExpand(command.getExpand()); + model.setValue(new ObjectVO(value, command.getExpand())); model.setSizeLimit(command.getSizeLimit()); model.setClassName(advice.getClazz().getName()); model.setMethodName(advice.getMethod().getName()); diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/GetStaticView.java b/core/src/main/java/com/taobao/arthas/core/command/view/GetStaticView.java index 867f4259e..2a242bfc6 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/GetStaticView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/GetStaticView.java @@ -22,11 +22,10 @@ public class GetStaticView extends ResultView { process.write("\n"); return; } - int expand = result.getExpand(); if (result.getField() != null) { ObjectVO field = result.getField(); - String valueStr = StringUtils.objectToString(expand >= 0 ? new ObjectView(field.getValue(), expand).draw() : field.getValue()); - process.write("field: " + field.getName() + "\n" + valueStr + "\n"); + String valueStr = StringUtils.objectToString(field.needExpand() ? new ObjectView(field).draw() : field.getObject()); + process.write("field: " + result.getFieldName() + "\n" + valueStr + "\n"); } else if (result.getMatchedClasses() != null) { Element table = ClassUtils.renderMatchedClasses(result.getMatchedClasses()); process.write(RenderUtil.render(table)).write("\n"); diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/OgnlView.java b/core/src/main/java/com/taobao/arthas/core/command/view/OgnlView.java index 176627201..ab7940f56 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/OgnlView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/OgnlView.java @@ -1,5 +1,6 @@ package com.taobao.arthas.core.command.view; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.OgnlModel; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.StringUtils; @@ -19,9 +20,8 @@ public class OgnlView extends ResultView { return; } - int expand = model.getExpand(); - Object value = model.getValue(); - String resultStr = StringUtils.objectToString(expand >= 0 ? new ObjectView(value, expand).draw() : value); + ObjectVO objectVO = model.getValue(); + String resultStr = StringUtils.objectToString(objectVO.needExpand() ? new ObjectView(objectVO).draw() : objectVO.getObject()); process.write(resultStr).write("\n"); } } diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/SearchClassView.java b/core/src/main/java/com/taobao/arthas/core/command/view/SearchClassView.java index fb5235fd2..2b7e907ba 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/SearchClassView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/SearchClassView.java @@ -1,5 +1,6 @@ package com.taobao.arthas.core.command.view; +import com.taobao.arthas.core.command.model.FieldVO; import com.taobao.arthas.core.command.model.SearchClassModel; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.ClassUtils; @@ -20,7 +21,7 @@ public class SearchClassView extends ResultView { if (result.isDetailed()) { process.write(RenderUtil.render(ClassUtils.renderClassInfo(result.getClassInfo(), - result.isWithField(), result.getExpand()), process.width())); + result.isWithField()), process.width())); process.write("\n"); } else if (result.getClassNames() != null) { for (String className : result.getClassNames()) { 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 51c9ad533..12922ed46 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 @@ -1,5 +1,6 @@ package com.taobao.arthas.core.command.view; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.TimeFragmentVO; import com.taobao.arthas.core.command.model.TimeTunnelModel; import com.taobao.arthas.core.command.monitor200.TimeTunnelTable; @@ -21,8 +22,6 @@ public class TimeTunnelView extends ResultView { @Override public void draw(CommandProcess process, TimeTunnelModel timeTunnelModel) { - Integer expand = timeTunnelModel.getExpand(); - boolean isNeedExpand = isNeedExpand(expand); Integer sizeLimit = timeTunnelModel.getSizeLimit(); if (timeTunnelModel.getTimeFragmentList() != null) { @@ -35,25 +34,25 @@ public class TimeTunnelView extends ResultView { TimeFragmentVO tf = timeTunnelModel.getTimeFragment(); TableElement table = TimeTunnelTable.createDefaultTable(); TimeTunnelTable.drawTimeTunnel(table, tf); - TimeTunnelTable.drawParameters(table, tf.getParams(), isNeedExpand, expand); - TimeTunnelTable.drawReturnObj(table, tf, isNeedExpand, expand, sizeLimit); - TimeTunnelTable.drawThrowException(table, tf, isNeedExpand, expand); + TimeTunnelTable.drawParameters(table, tf.getParams()); + TimeTunnelTable.drawReturnObj(table, tf, sizeLimit); + TimeTunnelTable.drawThrowException(table, tf); process.write(RenderUtil.render(table, process.width())); } else if (timeTunnelModel.getWatchValue() != null) { //watch single TimeFragment: tt -i 1000 -w 'params' - Object value = timeTunnelModel.getWatchValue(); - if (isNeedExpand) { - process.write(new ObjectView(value, expand, sizeLimit).draw()).write("\n"); + ObjectVO valueVO = timeTunnelModel.getWatchValue(); + if (valueVO.needExpand()) { + process.write(new ObjectView(sizeLimit, valueVO).draw()).write("\n"); } else { - process.write(StringUtils.objectToString(value)).write("\n"); + process.write(StringUtils.objectToString(valueVO.getObject())).write("\n"); } } else if (timeTunnelModel.getWatchResults() != null) { //search & watch: tt -s 'returnObj!=null' -w 'returnObj' TableElement table = TimeTunnelTable.createDefaultTable(); TimeTunnelTable.drawWatchTableHeader(table); - TimeTunnelTable.drawWatchResults(table, timeTunnelModel.getWatchResults(), isNeedExpand, expand, sizeLimit); + TimeTunnelTable.drawWatchResults(table, timeTunnelModel.getWatchResults(), sizeLimit); process.write(RenderUtil.render(table, process.width())); } else if (timeTunnelModel.getReplayResult() != null) { @@ -62,11 +61,11 @@ public class TimeTunnelView extends ResultView { Integer replayNo = timeTunnelModel.getReplayNo(); TableElement table = TimeTunnelTable.createDefaultTable(); TimeTunnelTable.drawPlayHeader(replayResult.getClassName(), replayResult.getMethodName(), replayResult.getObject(), replayResult.getIndex(), table); - TimeTunnelTable.drawParameters(table, replayResult.getParams(), isNeedExpand, expand); + TimeTunnelTable.drawParameters(table, replayResult.getParams()); if (replayResult.isReturn()) { - TimeTunnelTable.drawPlayResult(table, replayResult.getReturnObj(), isNeedExpand, expand, sizeLimit, replayResult.getCost()); + TimeTunnelTable.drawPlayResult(table, replayResult.getReturnObj(), sizeLimit, replayResult.getCost()); } else { - TimeTunnelTable.drawPlayException(table, replayResult.getThrowExp(), isNeedExpand, expand); + TimeTunnelTable.drawPlayException(table, replayResult.getThrowExp()); } process.write(RenderUtil.render(table, process.width())) .write(format("Time fragment[%d] successfully replayed %d times.", replayResult.getIndex(), replayNo)) @@ -74,8 +73,4 @@ public class TimeTunnelView extends ResultView { } } - private boolean isNeedExpand(Integer expand) { - return null != expand && expand > 0; - } - } diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/VmToolView.java b/core/src/main/java/com/taobao/arthas/core/command/view/VmToolView.java index a9641f178..6ef9d9257 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/VmToolView.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/VmToolView.java @@ -1,5 +1,6 @@ package com.taobao.arthas.core.command.view; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.VmToolModel; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.StringUtils; @@ -20,9 +21,8 @@ public class VmToolView extends ResultView { return; } - int expand = model.getExpand(); - Object value = model.getValue(); - String resultStr = StringUtils.objectToString(expand >= 0 ? new ObjectView(value, expand).draw() : value); + ObjectVO objectVO = model.getValue(); + String resultStr = StringUtils.objectToString(objectVO.needExpand() ? new ObjectView(objectVO).draw() : objectVO.getObject()); process.write(resultStr).write("\n"); } } 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 b74e3f174..c8e4eece3 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 @@ -1,5 +1,6 @@ package com.taobao.arthas.core.command.view; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.command.model.WatchModel; import com.taobao.arthas.core.shell.command.CommandProcess; import com.taobao.arthas.core.util.DateUtils; @@ -15,15 +16,10 @@ public class WatchView extends ResultView { @Override public void draw(CommandProcess process, WatchModel model) { - Object value = model.getValue(); + ObjectVO objectVO = model.getValue(); String result = StringUtils.objectToString( - isNeedExpand(model) ? new ObjectView(value, model.getExpand(), model.getSizeLimit()).draw() : value); + objectVO.needExpand() ? new ObjectView(model.getSizeLimit(), objectVO).draw() : objectVO.getObject()); process.write("method=" + model.getClassName() + "." + model.getMethodName() + " location=" + model.getAccessPoint() + "\n"); process.write("ts=" + DateUtils.formatDate(model.getTs()) + "; [cost=" + model.getCost() + "ms] result=" + result + "\n"); } - - private boolean isNeedExpand(WatchModel model) { - Integer expand = model.getExpand(); - return null != expand && expand >= 0; - } } diff --git a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/HttpApiHandler.java b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/HttpApiHandler.java index 2dbf88b69..8d50d9691 100644 --- a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/HttpApiHandler.java +++ b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/HttpApiHandler.java @@ -3,6 +3,10 @@ package com.taobao.arthas.core.shell.term.impl.http.api; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializeConfig; +import com.alibaba.fastjson.serializer.SerializeFilter; +import com.alibaba.fastjson.serializer.ValueFilter; +import com.alibaba.fastjson.util.IOUtils; import com.taobao.arthas.common.ArthasConstants; import com.taobao.arthas.common.PidUtils; import com.taobao.arthas.core.command.model.*; @@ -56,6 +60,7 @@ import java.util.concurrent.TimeUnit; public class HttpApiHandler { private static final Logger logger = LoggerFactory.getLogger(HttpApiHandler.class); + private static final ValueFilter[] JSON_FILTERS = new ValueFilter[] { new ObjectVOFilter() }; private static final String ONETIME_SESSION_KEY = "oneTimeSession"; public static final int DEFAULT_EXEC_TIMEOUT = 30000; private final SessionManager sessionManager; @@ -174,7 +179,7 @@ public class HttpApiHandler { private void writeResult(DefaultFullHttpResponse response, Object result) throws IOException { ByteBufOutputStream out = new ByteBufOutputStream(response.content()); try { - JSON.writeJSONString(out, result); + JSON.writeJSONString(out, IOUtils.UTF8, result, SerializeConfig.globalInstance, JSON_FILTERS, null, JSON.DEFAULT_GENERATE_FEATURE); } catch (IOException e) { logger.error("write json to response failed", e); throw e; diff --git a/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ObjectVOFilter.java b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ObjectVOFilter.java new file mode 100644 index 000000000..daf375755 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/shell/term/impl/http/api/ObjectVOFilter.java @@ -0,0 +1,25 @@ +package com.taobao.arthas.core.shell.term.impl.http.api; + +import com.alibaba.fastjson.serializer.ValueFilter; +import com.taobao.arthas.core.command.model.ObjectVO; +import com.taobao.arthas.core.util.StringUtils; +import com.taobao.arthas.core.view.ObjectView; + +/** + * @author hengyunabc 2022-08-24 + * + */ +public class ObjectVOFilter implements ValueFilter { + + @Override + public Object process(Object object, String name, Object value) { + + if (value instanceof ObjectVO) { + ObjectVO vo = (ObjectVO) value; + String resultStr = StringUtils.objectToString(vo.needExpand() ? new ObjectView(vo).draw() : value); + return resultStr; + } + return value; + } + +} diff --git a/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java b/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java index 15a00b26a..237fc23d4 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/util/ClassUtils.java @@ -42,10 +42,10 @@ public class ClassUtils { } public static Element renderClassInfo(ClassDetailVO clazz) { - return renderClassInfo(clazz, false, null); + return renderClassInfo(clazz, false); } - public static Element renderClassInfo(ClassDetailVO clazz, boolean isPrintField, Integer expand) { + public static Element renderClassInfo(ClassDetailVO clazz, boolean isPrintField) { TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1); table.row(label("class-info").style(Decoration.bold.bold()), label(clazz.getClassInfo())) @@ -69,12 +69,12 @@ public class ClassUtils { .row(label("classLoaderHash").style(Decoration.bold.bold()), label(clazz.getClassLoaderHash())); if (isPrintField) { - table.row(label("fields").style(Decoration.bold.bold()), TypeRenderUtils.drawField(clazz, expand)); + table.row(label("fields").style(Decoration.bold.bold()), TypeRenderUtils.drawField(clazz)); } return table; } - public static ClassDetailVO createClassInfo(Class clazz, boolean withFields) { + public static ClassDetailVO createClassInfo(Class clazz, boolean withFields, Integer expand) { CodeSource cs = clazz.getProtectionDomain().getCodeSource(); ClassDetailVO classInfo = new ClassDetailVO(); classInfo.setName(StringUtils.classname(clazz)); @@ -97,7 +97,7 @@ public class ClassUtils { classInfo.setClassloader(TypeRenderUtils.getClassloader(clazz)); classInfo.setClassLoaderHash(StringUtils.classLoaderHash(clazz)); if (withFields) { - classInfo.setFields(TypeRenderUtils.getFields(clazz)); + classInfo.setFields(TypeRenderUtils.getFields(clazz, expand)); } return classInfo; } diff --git a/core/src/main/java/com/taobao/arthas/core/util/TypeRenderUtils.java b/core/src/main/java/com/taobao/arthas/core/util/TypeRenderUtils.java index 64f9c7a14..6189f8699 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/TypeRenderUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/util/TypeRenderUtils.java @@ -3,6 +3,7 @@ package com.taobao.arthas.core.util; import com.taobao.arthas.core.command.model.ClassDetailVO; import com.taobao.arthas.core.command.model.ClassVO; import com.taobao.arthas.core.command.model.FieldVO; +import com.taobao.arthas.core.command.model.ObjectVO; import com.taobao.arthas.core.view.ObjectView; import com.taobao.text.ui.Element; import com.taobao.text.ui.TableElement; @@ -75,7 +76,7 @@ public class TypeRenderUtils { return root; } - public static Element drawField(ClassDetailVO clazz, Integer expand) { + public static Element drawField(ClassDetailVO clazz) { TableElement fieldsTable = new TableElement(1).leftCellPadding(0).rightCellPadding(0); FieldVO[] fields = clazz.getFields(); if (fields == null || fields.length == 0) { @@ -94,7 +95,8 @@ public class TypeRenderUtils { } if (field.isStatic()) { - Object o = (expand != null && expand >= 0) ? new ObjectView(field.getValue(), expand).draw() : field.getValue(); + ObjectVO objectVO = field.getValue(); + Object o = objectVO.needExpand() ? new ObjectView(objectVO).draw() : objectVO.getObject(); fieldTable.row("value", StringUtils.objectToString(o)); } @@ -160,7 +162,7 @@ public class TypeRenderUtils { return list.toArray(new String[0]); } - public static FieldVO[] getFields(Class clazz) { + public static FieldVO[] getFields(Class clazz, Integer expand) { Field[] fields = clazz.getDeclaredFields(); if (fields.length == 0) { return new FieldVO[0]; @@ -175,7 +177,7 @@ public class TypeRenderUtils { fieldVO.setAnnotations(getAnnotations(field.getAnnotations())); if (Modifier.isStatic(field.getModifiers())) { fieldVO.setStatic(true); - fieldVO.setValue(getFieldValue(field)); + fieldVO.setValue(new ObjectVO(getFieldValue(field), expand)); } else { fieldVO.setStatic(false); } 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 fb171cdc3..1883632e4 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 @@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.taobao.arthas.common.ArthasConstants; import com.taobao.arthas.core.GlobalOptions; +import com.taobao.arthas.core.command.model.ObjectVO; import java.io.PrintWriter; import java.io.StringWriter; @@ -29,6 +30,15 @@ public class ObjectView implements View { private final int deep; private final int maxObjectLength; + public ObjectView(ObjectVO objectVO) { + this(MAX_OBJECT_LENGTH, objectVO); + } + + // int参数在前面,防止构造函数二义性 + public ObjectView(int maxObjectLength, ObjectVO objectVO) { + this(objectVO.getObject(), objectVO.expandOrDefault(), maxObjectLength); + } + public ObjectView(Object object, int deep) { this(object, deep, MAX_OBJECT_LENGTH); }