mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
classloader command support load class. #246
This commit is contained in:
@@ -3,7 +3,10 @@ package com.taobao.arthas.core.command.klass100;
|
||||
import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.util.ClassUtils;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
import com.taobao.arthas.core.util.affect.RowAffect;
|
||||
import com.taobao.arthas.core.view.ObjectView;
|
||||
import com.taobao.middleware.cli.annotations.Description;
|
||||
import com.taobao.middleware.cli.annotations.Name;
|
||||
import com.taobao.middleware.cli.annotations.Option;
|
||||
@@ -38,10 +41,12 @@ import java.util.TreeSet;
|
||||
@Description(Constants.EXAMPLE +
|
||||
" classloader\n" +
|
||||
" classloader -t\n" +
|
||||
" classloader -l\n" +
|
||||
" classloader -c 327a647b\n" +
|
||||
" classloader -c 327a647b -r META-INF/MANIFEST.MF\n" +
|
||||
" classloader -a\n" +
|
||||
" classloader -a -c 327a647b\n" +
|
||||
" classloader -c 659e0bfd --load com.test.Demo\n" +
|
||||
Constants.WIKI + Constants.WIKI_HOME + "classloader")
|
||||
public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
private boolean isTree = false;
|
||||
@@ -51,6 +56,8 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
private boolean includeReflectionClassLoader = true;
|
||||
private boolean listClassLoader = false;
|
||||
|
||||
private String loadClass = null;
|
||||
|
||||
@Option(shortName = "t", longName = "tree", flag = true)
|
||||
@Description("Display ClassLoader tree")
|
||||
public void setTree(boolean tree) {
|
||||
@@ -87,6 +94,12 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
this.listClassLoader = listClassLoader;
|
||||
}
|
||||
|
||||
@Option(longName = "load")
|
||||
@Description("Use ClassLoader to load class, won't work without -c specified")
|
||||
public void setLoadClass(String className) {
|
||||
this.loadClass = className;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(CommandProcess process) {
|
||||
Instrumentation inst = process.session().getInstrumentation();
|
||||
@@ -94,6 +107,8 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
processAllClasses(process, inst);
|
||||
} else if (hashCode != null && resource != null) {
|
||||
processResources(process, inst);
|
||||
} else if (hashCode != null && this.loadClass != null) {
|
||||
processLoadClass(process, inst);
|
||||
} else if (hashCode != null) {
|
||||
processClassloader(process, inst);
|
||||
} else if (listClassLoader || isTree){
|
||||
@@ -169,8 +184,7 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
private void processResources(CommandProcess process, Instrumentation inst) {
|
||||
RowAffect affect = new RowAffect();
|
||||
int rowCount = 0;
|
||||
Set<ClassLoader> allClassLoader = includeReflectionClassLoader ? getAllClassLoader(inst) :
|
||||
getAllClassLoader(inst, new SunReflectionClassLoaderFilter());
|
||||
Set<ClassLoader> allClassLoader = getAllClassLoader(inst);
|
||||
for (ClassLoader cl : allClassLoader) {
|
||||
if (Integer.toHexString(cl.hashCode()).equals(hashCode)) {
|
||||
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
|
||||
@@ -192,6 +206,26 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
process.end();
|
||||
}
|
||||
|
||||
// Use ClassLoader to loadClass
|
||||
private void processLoadClass(CommandProcess process, Instrumentation inst) {
|
||||
Set<ClassLoader> allClassLoader = getAllClassLoader(inst);
|
||||
for (ClassLoader cl : allClassLoader) {
|
||||
if (Integer.toHexString(cl.hashCode()).equals(hashCode)) {
|
||||
try {
|
||||
Class<?> clazz = cl.loadClass(this.loadClass);
|
||||
process.write("load class success.\n");
|
||||
process.write(RenderUtil.render(ClassUtils.renderClassInfo(clazz), process.width()) + "\n");
|
||||
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
process.write("load class error.\n" + StringUtils.objectToString(new ObjectView(e, 1).draw()));
|
||||
}
|
||||
}
|
||||
}
|
||||
process.write("\n");
|
||||
process.end();
|
||||
}
|
||||
|
||||
private void processAllClasses(CommandProcess process, Instrumentation inst) {
|
||||
RowAffect affect = new RowAffect();
|
||||
process.write(RenderUtil.render(renderClasses(hashCode, inst), process.width()));
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.taobao.arthas.core.advisor.Enhancer;
|
||||
import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.util.ClassUtils;
|
||||
import com.taobao.arthas.core.util.FileUtils;
|
||||
import com.taobao.arthas.core.util.LogUtil;
|
||||
import com.taobao.arthas.core.util.SearchUtils;
|
||||
@@ -125,7 +126,7 @@ public class JadCommand extends AnnotatedCommand {
|
||||
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(SearchClassCommand.getCodeSource(
|
||||
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);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.taobao.arthas.core.command.klass100;
|
||||
|
||||
import static com.taobao.text.ui.Element.label;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.security.CodeSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -12,18 +10,15 @@ import java.util.List;
|
||||
import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.util.ClassUtils;
|
||||
import com.taobao.arthas.core.util.SearchUtils;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
import com.taobao.arthas.core.util.TypeRenderUtils;
|
||||
import com.taobao.arthas.core.util.affect.RowAffect;
|
||||
import com.taobao.middleware.cli.annotations.Argument;
|
||||
import com.taobao.middleware.cli.annotations.Description;
|
||||
import com.taobao.middleware.cli.annotations.Name;
|
||||
import com.taobao.middleware.cli.annotations.Option;
|
||||
import com.taobao.middleware.cli.annotations.Summary;
|
||||
import com.taobao.text.Decoration;
|
||||
import com.taobao.text.ui.Element;
|
||||
import com.taobao.text.ui.TableElement;
|
||||
import com.taobao.text.util.RenderUtil;
|
||||
|
||||
/**
|
||||
@@ -46,14 +41,6 @@ public class SearchClassCommand extends AnnotatedCommand {
|
||||
private boolean isRegEx = false;
|
||||
private Integer expand;
|
||||
|
||||
public static String getCodeSource(final CodeSource cs) {
|
||||
if (null == cs || null == cs.getLocation() || null == cs.getLocation().getFile()) {
|
||||
return com.taobao.arthas.core.util.Constants.EMPTY_STRING;
|
||||
}
|
||||
|
||||
return cs.getLocation().getFile();
|
||||
}
|
||||
|
||||
@Argument(argName = "class-pattern", index = 0)
|
||||
@Description("Class name pattern, use either '.' or '/' as separator")
|
||||
public void setClassPattern(String classPattern) {
|
||||
@@ -108,40 +95,10 @@ public class SearchClassCommand extends AnnotatedCommand {
|
||||
|
||||
private void processClass(CommandProcess process, Class<?> clazz) {
|
||||
if (isDetail) {
|
||||
process.write(RenderUtil.render(renderClassInfo(clazz, isField), process.width()) + "\n");
|
||||
process.write(RenderUtil.render(ClassUtils.renderClassInfo(clazz, isField, expand), process.width()) + "\n");
|
||||
} else {
|
||||
process.write(clazz.getName() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
private Element renderClassInfo(Class<?> clazz, boolean isPrintField) {
|
||||
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
|
||||
CodeSource cs = clazz.getProtectionDomain().getCodeSource();
|
||||
|
||||
table.row(label("class-info").style(Decoration.bold.bold()), label(StringUtils.classname(clazz)))
|
||||
.row(label("code-source").style(Decoration.bold.bold()), label(getCodeSource(cs)))
|
||||
.row(label("name").style(Decoration.bold.bold()), label(StringUtils.classname(clazz)))
|
||||
.row(label("isInterface").style(Decoration.bold.bold()), label("" + clazz.isInterface()))
|
||||
.row(label("isAnnotation").style(Decoration.bold.bold()), label("" + clazz.isAnnotation()))
|
||||
.row(label("isEnum").style(Decoration.bold.bold()), label("" + clazz.isEnum()))
|
||||
.row(label("isAnonymousClass").style(Decoration.bold.bold()), label("" + clazz.isAnonymousClass()))
|
||||
.row(label("isArray").style(Decoration.bold.bold()), label("" + clazz.isArray()))
|
||||
.row(label("isLocalClass").style(Decoration.bold.bold()), label("" + clazz.isLocalClass()))
|
||||
.row(label("isMemberClass").style(Decoration.bold.bold()), label("" + clazz.isMemberClass()))
|
||||
.row(label("isPrimitive").style(Decoration.bold.bold()), label("" + clazz.isPrimitive()))
|
||||
.row(label("isSynthetic").style(Decoration.bold.bold()), label("" + clazz.isSynthetic()))
|
||||
.row(label("simple-name").style(Decoration.bold.bold()), label(clazz.getSimpleName()))
|
||||
.row(label("modifier").style(Decoration.bold.bold()), label(StringUtils.modifier(clazz.getModifiers(), ',')))
|
||||
.row(label("annotation").style(Decoration.bold.bold()), label(TypeRenderUtils.drawAnnotation(clazz)))
|
||||
.row(label("interfaces").style(Decoration.bold.bold()), label(TypeRenderUtils.drawInterface(clazz)))
|
||||
.row(label("super-class").style(Decoration.bold.bold()), TypeRenderUtils.drawSuperClass(clazz))
|
||||
.row(label("class-loader").style(Decoration.bold.bold()), TypeRenderUtils.drawClassLoader(clazz))
|
||||
.row(label("classLoaderHash").style(Decoration.bold.bold()), label(StringUtils.classLoaderHash(clazz)));
|
||||
|
||||
if (isPrintField) {
|
||||
table.row(label("fields"), TypeRenderUtils.drawField(clazz, expand));
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.taobao.arthas.core.util;
|
||||
|
||||
import static com.taobao.text.ui.Element.label;
|
||||
|
||||
import java.security.CodeSource;
|
||||
|
||||
import com.taobao.text.Decoration;
|
||||
import com.taobao.text.ui.Element;
|
||||
import com.taobao.text.ui.TableElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2018-10-18
|
||||
*
|
||||
*/
|
||||
public class ClassUtils {
|
||||
|
||||
public static String getCodeSource(final CodeSource cs) {
|
||||
if (null == cs || null == cs.getLocation() || null == cs.getLocation().getFile()) {
|
||||
return com.taobao.arthas.core.util.Constants.EMPTY_STRING;
|
||||
}
|
||||
|
||||
return cs.getLocation().getFile();
|
||||
}
|
||||
|
||||
public static Element renderClassInfo(Class<?> clazz) {
|
||||
return renderClassInfo(clazz, false, null);
|
||||
}
|
||||
|
||||
public static Element renderClassInfo(Class<?> clazz, boolean isPrintField, Integer expand) {
|
||||
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
|
||||
CodeSource cs = clazz.getProtectionDomain().getCodeSource();
|
||||
|
||||
table.row(label("class-info").style(Decoration.bold.bold()), label(StringUtils.classname(clazz)))
|
||||
.row(label("code-source").style(Decoration.bold.bold()), label(getCodeSource(cs)))
|
||||
.row(label("name").style(Decoration.bold.bold()), label(StringUtils.classname(clazz)))
|
||||
.row(label("isInterface").style(Decoration.bold.bold()), label("" + clazz.isInterface()))
|
||||
.row(label("isAnnotation").style(Decoration.bold.bold()), label("" + clazz.isAnnotation()))
|
||||
.row(label("isEnum").style(Decoration.bold.bold()), label("" + clazz.isEnum()))
|
||||
.row(label("isAnonymousClass").style(Decoration.bold.bold()), label("" + clazz.isAnonymousClass()))
|
||||
.row(label("isArray").style(Decoration.bold.bold()), label("" + clazz.isArray()))
|
||||
.row(label("isLocalClass").style(Decoration.bold.bold()), label("" + clazz.isLocalClass()))
|
||||
.row(label("isMemberClass").style(Decoration.bold.bold()), label("" + clazz.isMemberClass()))
|
||||
.row(label("isPrimitive").style(Decoration.bold.bold()), label("" + clazz.isPrimitive()))
|
||||
.row(label("isSynthetic").style(Decoration.bold.bold()), label("" + clazz.isSynthetic()))
|
||||
.row(label("simple-name").style(Decoration.bold.bold()), label(clazz.getSimpleName()))
|
||||
.row(label("modifier").style(Decoration.bold.bold()), label(StringUtils.modifier(clazz.getModifiers(), ',')))
|
||||
.row(label("annotation").style(Decoration.bold.bold()), label(TypeRenderUtils.drawAnnotation(clazz)))
|
||||
.row(label("interfaces").style(Decoration.bold.bold()), label(TypeRenderUtils.drawInterface(clazz)))
|
||||
.row(label("super-class").style(Decoration.bold.bold()), TypeRenderUtils.drawSuperClass(clazz))
|
||||
.row(label("class-loader").style(Decoration.bold.bold()), TypeRenderUtils.drawClassLoader(clazz))
|
||||
.row(label("classLoaderHash").style(Decoration.bold.bold()), label(StringUtils.classLoaderHash(clazz)));
|
||||
|
||||
if (isPrintField) {
|
||||
table.row(label("fields"), TypeRenderUtils.drawField(clazz, expand));
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user