系列
开篇
- Arthas通过classloader 命令将 JVM 中所有的classloader的信息统计出来,并可以展示继承树,urls等。可以让指定的classloader去getResources,打印出所有查找到的resources的url。对于ResourceNotFoundException比较有用。
- Arthas的classloader的查找本质也是通过Instrumentation获取所有的加载的class,然后通过class的getClassLoader方法查找对应的ClassLoader对象。
classloader查找流程
public class ClassLoaderCommand extends AnnotatedCommand {
private void getAllClasses(String hashCode, Instrumentation inst, RowAffect affect, CommandProcess process) {
int hashCodeInt = -1;
if (hashCode != null) {
hashCodeInt = Integer.valueOf(hashCode, 16);
}
// bootstrapClassSet保存class
SortedSet<Class<?>> bootstrapClassSet = new TreeSet<Class<?>>(new Comparator<Class>() {
@Override
public int compare(Class o1, Class o2) {
return o1.getName().compareTo(o2.getName());
}
});
// 通过inst.getAllLoadedClasses获取所有加载的类
Class[] allLoadedClasses = inst.getAllLoadedClasses();
// classLoaderClassMap保存类加载器和对应的class
Map<ClassLoader, SortedSet<Class<?>>> classLoaderClassMap = new HashMap<ClassLoader, SortedSet<Class<?>>>();
for (Class clazz : allLoadedClasses) {
// 获取类对应的类加载器
ClassLoader classLoader = clazz.getClassLoader();
// Class loaded by BootstrapClassLoader
if (classLoader == null) {
if (hashCode == null) {
bootstrapClassSet.add(clazz);
}
continue;
}
if (hashCode != null && classLoader.hashCode() != hashCodeInt) {
continue;
}
SortedSet<Class<?>> classSet = classLoaderClassMap.get(classLoader);
if (classSet == null) {
classSet = new TreeSet<Class<?>>(new Comparator<Class<?>>() {
@Override
public int compare(Class<?> o1, Class<?> o2) {
return o1.getName().compareTo(o2.getName());
}
});
classLoaderClassMap.put(classLoader, classSet);
}
classSet.add(clazz);
}
}
}
- ClassLoaderCommand通过getAllClasses来获取类加载器classloader。
- 通过Instrumentation.getAllLoadedClasses获取所有的class,通过class.getClassLoader获取对应的类加载器。
public class ClassLoaderVO {
private String name;
private String hash;
private String parent;
private Integer loadedCount;
private Integer numberOfInstances;
private List<ClassLoaderVO> children;
public ClassLoaderVO() {
}
public void addChild(ClassLoaderVO child){
if (this.children == null){
this.children = new ArrayList<ClassLoaderVO>();
}
this.children.add(child);
}
}
- 构造类加载器的树形结构主要是通过ClassLoaderVO对象,每个类加载器的VO对象包含子节点列表的children。
网友评论