classloader command support load class. #246

pull/539/head
hengyunabc 6 years ago
parent 13684c5718
commit 65fc3bf583

@ -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;
}
}
Loading…
Cancel
Save