mirror of
https://gitee.com/arthas/arthas.git
synced 2024-12-03 12:48:48 +08:00
Classloader support matching classloader by class name. (#1428)
This commit is contained in:
parent
92dd9a2fb0
commit
3dc3f36b9d
@ -13,6 +13,7 @@ import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.shell.handlers.Handler;
|
||||
import com.taobao.arthas.core.util.ClassUtils;
|
||||
import com.taobao.arthas.core.util.ClassLoaderUtils;
|
||||
import com.taobao.arthas.core.util.ResultUtils;
|
||||
import com.taobao.arthas.core.util.affect.RowAffect;
|
||||
import com.taobao.middleware.cli.annotations.Description;
|
||||
@ -56,6 +57,7 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
private Logger logger = LoggerFactory.getLogger(ClassLoaderCommand.class);
|
||||
private boolean isTree = false;
|
||||
private String hashCode;
|
||||
private String classLoaderClass;
|
||||
private boolean all = false;
|
||||
private String resource;
|
||||
private boolean includeReflectionClassLoader = true;
|
||||
@ -70,6 +72,12 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
public void setTree(boolean tree) {
|
||||
isTree = tree;
|
||||
}
|
||||
|
||||
@Option(longName = "classLoaderClass")
|
||||
@Description("The class name of the special class's classLoader.")
|
||||
public void setClassLoaderClass(String classLoaderClass) {
|
||||
this.classLoaderClass = classLoaderClass;
|
||||
}
|
||||
|
||||
@Option(shortName = "c", longName = "classloader")
|
||||
@Description("The hash code of the special ClassLoader")
|
||||
@ -113,6 +121,25 @@ public class ClassLoaderCommand extends AnnotatedCommand {
|
||||
process.interruptHandler(new ClassLoaderInterruptHandler(this));
|
||||
|
||||
Instrumentation inst = process.session().getInstrumentation();
|
||||
|
||||
if (!all && hashCode == null && classLoaderClass != null) {
|
||||
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, classLoaderClass);
|
||||
if (matchedClassLoaders.size() == 1) {
|
||||
hashCode = "" + Integer.toHexString(matchedClassLoaders.get(0).hashCode());
|
||||
} else if (matchedClassLoaders.size() > 1) {
|
||||
Collection<ClassLoaderVO> classLoaderVOList = ClassUtils.createClassLoaderVOList(matchedClassLoaders);
|
||||
ClassLoaderModel classloaderModel = new ClassLoaderModel()
|
||||
.setClassLoaderClass(classLoaderClass)
|
||||
.setMatchedClassLoaders(classLoaderVOList);
|
||||
process.appendResult(classloaderModel);
|
||||
process.end(-1, "Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'");
|
||||
return;
|
||||
} else {
|
||||
process.end(-1, "Can not find classloader by class name: " + classLoaderClass + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (all) {
|
||||
processAllClasses(process, inst);
|
||||
} else if (hashCode != null && resource != null) {
|
||||
|
@ -4,6 +4,7 @@ import com.taobao.arthas.core.command.klass100.ClassLoaderCommand.ClassLoaderSta
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author gongdewei 2020/4/21
|
||||
@ -20,6 +21,9 @@ public class ClassLoaderModel extends ResultModel {
|
||||
|
||||
private Map<String, ClassLoaderStat> classLoaderStats;
|
||||
|
||||
private Collection<ClassLoaderVO> matchedClassLoaders;
|
||||
private String classLoaderClass;
|
||||
|
||||
public ClassLoaderModel() {
|
||||
}
|
||||
|
||||
@ -90,4 +94,22 @@ public class ClassLoaderModel extends ResultModel {
|
||||
this.classLoaderStats = classLoaderStats;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getClassLoaderClass() {
|
||||
return classLoaderClass;
|
||||
}
|
||||
|
||||
public ClassLoaderModel setClassLoaderClass(String classLoaderClass) {
|
||||
this.classLoaderClass = classLoaderClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Collection<ClassLoaderVO> getMatchedClassLoaders() {
|
||||
return matchedClassLoaders;
|
||||
}
|
||||
|
||||
public ClassLoaderModel setMatchedClassLoaders(Collection<ClassLoaderVO> matchedClassLoaders) {
|
||||
this.matchedClassLoaders = matchedClassLoaders;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,12 @@ public class ClassLoaderView extends ResultView<ClassLoaderModel> {
|
||||
|
||||
@Override
|
||||
public void draw(CommandProcess process, ClassLoaderModel result) {
|
||||
if (result.getMatchedClassLoaders() != null) {
|
||||
process.write("Matched classloaders: \n");
|
||||
drawClassLoaders(process, result.getMatchedClassLoaders(), false);
|
||||
process.write("\n");
|
||||
return;
|
||||
}
|
||||
if (result.getClassSet() != null) {
|
||||
drawAllClasses(process, result.getClassSet());
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ classloader
|
||||
|[t]|打印所有ClassLoader的继承树|
|
||||
|[a]|列出所有ClassLoader加载的类,请谨慎使用|
|
||||
|`[c:]`|ClassLoader的hashcode|
|
||||
|`[classLoaderClass:]`|指定执行表达式的 ClassLoader 的 class name|
|
||||
|`[c: r:]`|用ClassLoader去查找resource|
|
||||
|`[c: load:]`|用ClassLoader去加载指定的类|
|
||||
|
||||
@ -67,6 +68,18 @@ file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar
|
||||
Affect(row-cnt:9) cost in 3 ms.
|
||||
```
|
||||
|
||||
*注意* hashcode是变化的,需要先查看当前的ClassLoader信息,提取对应ClassLoader的hashcode。
|
||||
|
||||
对于只有唯一实例的ClassLoader可以通过class name指定,使用起来更加方便:
|
||||
|
||||
```bash
|
||||
$ classloader --classLoaderClass sun.misc.Launcher$AppClassLoader
|
||||
file:/private/tmp/arthas-demo.jar
|
||||
file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar
|
||||
|
||||
Affect(row-cnt:9) cost in 3 ms.
|
||||
```
|
||||
|
||||
#### 使用ClassLoader去查找resource
|
||||
|
||||
```bash
|
||||
|
@ -13,6 +13,7 @@ View hierarchy, urls and classes-loading info for the class-loaders.
|
||||
|[t]|print classloader's hierarchy|
|
||||
|[a]|list all the classes loaded by all the classloaders (use it with great caution since the output can be huge)|
|
||||
|[c:]|print classloader's hashcode|
|
||||
|`[classLoaderClass:]`| The class name of the ClassLoader that executes the expression. |
|
||||
|`[c: r:]`|using ClassLoader to search resource|
|
||||
|`[c: load:]`|using ClassLoader to load class|
|
||||
|
||||
@ -64,6 +65,18 @@ file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar
|
||||
Affect(row-cnt:9) cost in 3 ms.
|
||||
```
|
||||
|
||||
Note that the hashcode changes, you need to check the current ClassLoader information first, and extract the hashcode corresponding to the ClassLoader.
|
||||
|
||||
For ClassLoader with only unique instance, it can be specified by class name, which is more convenient to use:
|
||||
|
||||
```bash
|
||||
$ classloader --classLoaderClass sun.misc.Launcher$AppClassLoader
|
||||
file:/private/tmp/arthas-demo.jar
|
||||
file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar
|
||||
|
||||
Affect(row-cnt:9) cost in 3 ms.
|
||||
```
|
||||
|
||||
#### Use the classloader to load resource
|
||||
|
||||
```bash
|
||||
|
Loading…
Reference in New Issue
Block a user