From e0bfc73134ae270a7993400aab7d5bbcda3a9e57 Mon Sep 17 00:00:00 2001 From: gongdewei Date: Wed, 22 Apr 2020 16:21:44 +0800 Subject: [PATCH] transform command: jad --- .../core/command/klass100/JadCommand.java | 68 +++++++++---------- .../arthas/core/command/model/JadModel.java | 42 ++++++++++++ .../core/command/model/StatusModel.java | 8 +-- .../arthas/core/command/view/JadView.java | 34 ++++++++++ .../core/command/view/ResultViewResolver.java | 1 + 5 files changed, 112 insertions(+), 41 deletions(-) create mode 100644 core/src/main/java/com/taobao/arthas/core/command/model/JadModel.java create mode 100644 core/src/main/java/com/taobao/arthas/core/command/view/JadView.java diff --git a/core/src/main/java/com/taobao/arthas/core/command/klass100/JadCommand.java b/core/src/main/java/com/taobao/arthas/core/command/klass100/JadCommand.java index fbb2bb6f9..56cdd81c6 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/klass100/JadCommand.java +++ b/core/src/main/java/com/taobao/arthas/core/command/klass100/JadCommand.java @@ -3,6 +3,7 @@ package com.taobao.arthas.core.command.klass100; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.taobao.arthas.core.command.Constants; +import com.taobao.arthas.core.command.model.*; import com.taobao.arthas.core.shell.cli.Completion; import com.taobao.arthas.core.shell.cli.CompletionUtils; import com.taobao.arthas.core.shell.command.AnnotatedCommand; @@ -20,21 +21,18 @@ import com.taobao.middleware.cli.annotations.Summary; import com.taobao.text.Color; import com.taobao.text.Decoration; import com.taobao.text.lang.LangRenderUtil; -import com.taobao.text.ui.Element; import com.taobao.text.ui.LabelElement; -import com.taobao.text.ui.TableElement; import com.taobao.text.util.RenderUtil; import java.io.File; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; -import static com.taobao.text.ui.Element.label; - /** * @author diecui1202 on 15/11/24. * @author hengyunabc 2018-11-16 @@ -99,24 +97,25 @@ public class JadCommand extends AnnotatedCommand { Instrumentation inst = process.session().getInstrumentation(); Set> matchedClasses = SearchUtils.searchClassOnly(inst, classPattern, isRegEx, code); + StatusModel statusModel = new StatusModel(-1, "unknown error"); try { if (matchedClasses == null || matchedClasses.isEmpty()) { - processNoMatch(process); + statusModel = processNoMatch(process); } else if (matchedClasses.size() > 1) { - processMatches(process, matchedClasses); + statusModel = processMatches(process, matchedClasses); } else { // matchedClasses size is 1 // find inner classes. Set> withInnerClasses = SearchUtils.searchClassOnly(inst, matchedClasses.iterator().next().getName() + "$*", false, code); if(withInnerClasses.isEmpty()) { withInnerClasses = matchedClasses; } - processExactMatch(process, affect, inst, matchedClasses, withInnerClasses); + statusModel = processExactMatch(process, affect, inst, matchedClasses, withInnerClasses); } } finally { if (!this.sourceOnly) { - process.write(affect + "\n"); + process.appendResult(new RowAffectModel(affect)); } - process.end(); + process.end(statusModel.getStatusCode(), statusModel.getMessage()); } } @@ -141,7 +140,8 @@ public class JadCommand extends AnnotatedCommand { } } - private void processExactMatch(CommandProcess process, RowAffect affect, Instrumentation inst, Set> matchedClasses, Set> withInnerClasses) { + private StatusModel processExactMatch(CommandProcess process, RowAffect affect, Instrumentation inst, Set> matchedClasses, Set> withInnerClasses) { + StatusModel statusModel = new StatusModel(); Class c = matchedClasses.iterator().next(); Set> allClasses = new HashSet>(withInnerClasses); allClasses.add(c); @@ -160,46 +160,40 @@ public class JadCommand extends AnnotatedCommand { source = "unknown"; } - if (this.sourceOnly) { - process.write(LangRenderUtil.render(source) + "\n"); - return; + JadModel jadModel = new JadModel(); + jadModel.setSource(source); + if (!this.sourceOnly) { + jadModel.setClassInfo(ClassUtils.createSimpleClassInfo(c)); + jadModel.setLocation(ClassUtils.getCodeSource(c.getProtectionDomain().getCodeSource())); } + process.appendResult(jadModel); - - process.write("\n"); - process.write(RenderUtil.render(new LabelElement("ClassLoader: ").style(Decoration.bold.fg(Color.red)), process.width())); - process.write(RenderUtil.render(TypeRenderUtils.drawClassLoader(c), process.width()) + "\n"); - process.write(RenderUtil.render(new LabelElement("Location: ").style(Decoration.bold.fg(Color.red)), process.width())); - process.write(RenderUtil.render(new LabelElement(ClassUtils.getCodeSource( - c.getProtectionDomain().getCodeSource())).style(Decoration.bold.fg(Color.blue)), process.width()) + "\n"); - process.write(LangRenderUtil.render(source) + "\n"); - process.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING); affect.rCnt(classFiles.keySet().size()); + statusModel.setStatus(0); } catch (Throwable t) { logger.error("jad: fail to decompile class: " + c.getName(), t); + statusModel.setStatus(-1, "jad: fail to decompile class: " + c.getName()); } + return statusModel; } - private void processMatches(CommandProcess process, Set> matchedClasses) { - Element usage = new LabelElement("jad -c " + classPattern).style(Decoration.bold.fg(Color.blue)); - process.write("\n Found more than one class for: " + classPattern + ", Please use " - + RenderUtil.render(usage, process.width())); + private StatusModel processMatches(CommandProcess process, Set> matchedClasses) { + //Element usage = new LabelElement("jad -c " + classPattern).style(Decoration.bold.fg(Color.blue)); + //process.write("\n Found more than one class for: " + classPattern + ", Please use " + // + RenderUtil.render(usage, process.width())); - TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1); - table.row(new LabelElement("HASHCODE").style(Decoration.bold.bold()), - new LabelElement("CLASSLOADER").style(Decoration.bold.bold())); + String usage = "jad -c " + classPattern; + String msg = " Found more than one class for: " + classPattern + ", Please use " + usage; + process.appendResult(new MessageModel(msg)); - for (Class c : matchedClasses) { - ClassLoader classLoader = c.getClassLoader(); - table.row(label(Integer.toHexString(classLoader.hashCode())).style(Decoration.bold.fg(Color.red)), - TypeRenderUtils.drawClassLoader(c)); - } + List classVOs = ClassUtils.createClassVOList(matchedClasses); + process.appendResult(new ClassMatchesModel(classVOs)); - process.write(RenderUtil.render(table, process.width()) + "\n"); + return new StatusModel(-1, msg); } - private void processNoMatch(CommandProcess process) { - process.write("No class found for: " + classPattern + "\n"); + private StatusModel processNoMatch(CommandProcess process) { + return new StatusModel().setStatus(-1, "No class found for: " + classPattern); } @Override diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/JadModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/JadModel.java new file mode 100644 index 000000000..d75677425 --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/model/JadModel.java @@ -0,0 +1,42 @@ +package com.taobao.arthas.core.command.model; + +/** + * @author gongdewei 2020/4/22 + */ +public class JadModel extends ResultModel { + private ClassVO classInfo; + private String location; + private String source; + + @Override + public String getType() { + return "jad"; + } + + public JadModel() { + } + + public ClassVO getClassInfo() { + return classInfo; + } + + public void setClassInfo(ClassVO classInfo) { + this.classInfo = classInfo; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/model/StatusModel.java b/core/src/main/java/com/taobao/arthas/core/command/model/StatusModel.java index 7ec8d17f8..c4a53b895 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/model/StatusModel.java +++ b/core/src/main/java/com/taobao/arthas/core/command/model/StatusModel.java @@ -30,14 +30,14 @@ public class StatusModel extends ResultModel { return this; } - public void setStatus(int statusCode, String message) { + public StatusModel setStatus(int statusCode, String message) { this.statusCode = statusCode; this.message = message; + return this; } - public void setStatus(int statusCode) { - this.statusCode = statusCode; - this.message = null; + public StatusModel setStatus(int statusCode) { + return this.setStatus(statusCode, null); } @Override diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/JadView.java b/core/src/main/java/com/taobao/arthas/core/command/view/JadView.java new file mode 100644 index 000000000..dde205baa --- /dev/null +++ b/core/src/main/java/com/taobao/arthas/core/command/view/JadView.java @@ -0,0 +1,34 @@ +package com.taobao.arthas.core.command.view; + +import com.taobao.arthas.core.command.model.ClassVO; +import com.taobao.arthas.core.command.model.JadModel; +import com.taobao.arthas.core.shell.command.CommandProcess; +import com.taobao.arthas.core.util.TypeRenderUtils; +import com.taobao.text.Color; +import com.taobao.text.Decoration; +import com.taobao.text.lang.LangRenderUtil; +import com.taobao.text.ui.LabelElement; +import com.taobao.text.util.RenderUtil; + +/** + * @author gongdewei 2020/4/22 + */ +public class JadView extends ResultView { + + @Override + public void draw(CommandProcess process, JadModel result) { + ClassVO classInfo = result.getClassInfo(); + if (classInfo != null) { + process.write("\n"); + process.write(RenderUtil.render(new LabelElement("ClassLoader: ").style(Decoration.bold.fg(Color.red)), process.width())); + process.write(RenderUtil.render(TypeRenderUtils.drawClassLoader(classInfo), process.width()) + "\n"); + } + if (result.getLocation() != null) { + process.write(RenderUtil.render(new LabelElement("Location: ").style(Decoration.bold.fg(Color.red)), process.width())); + process.write(RenderUtil.render(new LabelElement(result.getLocation()).style(Decoration.bold.fg(Color.blue)), process.width()) + "\n"); + } + process.write(LangRenderUtil.render(result.getSource()) + "\n"); + process.write(com.taobao.arthas.core.util.Constants.EMPTY_STRING); + } + +} diff --git a/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java b/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java index 3f91d1335..f66a14a12 100644 --- a/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java +++ b/core/src/main/java/com/taobao/arthas/core/command/view/ResultViewResolver.java @@ -55,6 +55,7 @@ public class ResultViewResolver { registerView(new GetStaticModel(), new GetStaticView()); registerView(new DumpClassModel(), new DumpClassView()); registerView(new ClassLoaderModel(), new ClassLoaderView()); + registerView(new JadModel(), new JadView()); } catch (Throwable e) { logger.error("register result view failed", e); }