题记:
看到InfoQ关于ClassLoader的文章,挺给力。自己对ClassLoader有更全面的认知。
Java编译成class给JVM运行,JVM通过ClassLoader去load这个class并为每个class有且只生成一个Class类,以后这个Class就可以生成instance实例了。为了保护某个类不重复加载,JVM就需要在加载class的时候去查询,这个工作由ClassLoader的findLoadedClass和findBootstrapClass0来做。 ClassLoader也搞了个继承,处于最顶层是BootstrapClass,然后ExtClassLoader,然后AppClassLoader。那到底先从哪个ClassLoader开始呢?
先从当前ClassLoader开始,ClassLoader代码如下:
除开其他关于loadResource的方法,只有一个loadClass的public方法,如下:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 首先,查询名为name的class有没有加载过
Class c = findLoadedClass(name); // 查询当前ClassLoader有没有加载过
if (c == null) { // 如果没有
try {
if (parent != null) {
c = parent.loadClass(name, false); // 查询上层LoadClass有没有加载过
} else {
c = findBootstrapClass0(name); // 一直遍历到了BootstrapClassLoader,native方法 }
} catch (ClassNotFoundException e) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name); // 可扩展点
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
所以写自己的ClassLoader可以override findClass方法,然后调用protected final Class<?> defineClass(String name, byte[] b, int off, int len)来加载class了。
当然你也可以只override loadClass方法,但什么都不做。然后调用defineClass来尝试加载同一个class,我不知道会怎样,还没有尝试过,有人尝试记得告诉我一声。
所以写自己的ClassLoader,就可以这样:
class MyCL extends ClassLoader{
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
...
}
}