transform command: jad

This commit is contained in:
gongdewei
2020-04-22 16:21:44 +08:00
parent f4b81db42b
commit e0bfc73134
5 changed files with 112 additions and 41 deletions
@@ -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<Class<?>> 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<Class<?>> 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<Class<?>> matchedClasses, Set<Class<?>> withInnerClasses) {
private StatusModel processExactMatch(CommandProcess process, RowAffect affect, Instrumentation inst, Set<Class<?>> matchedClasses, Set<Class<?>> withInnerClasses) {
StatusModel statusModel = new StatusModel();
Class<?> c = matchedClasses.iterator().next();
Set<Class<?>> allClasses = new HashSet<Class<?>>(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<Class<?>> matchedClasses) {
Element usage = new LabelElement("jad -c <hashcode> " + 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<Class<?>> matchedClasses) {
//Element usage = new LabelElement("jad -c <hashcode> " + 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 <hashcode> " + 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<ClassVO> 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
@@ -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;
}
}
@@ -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
@@ -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<JadModel> {
@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);
}
}
@@ -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);
}