mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
transform command: jad
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user