实现自定义 classLoader
每个自定义加载器必须直接或间接扩展 java.lang.ClassLoader
类。主要的扩展点是以下方法:
findClass(String)
- 如果类加载器遵循类加载的标准委托模型,则重载此方法。loadClass(String, boolean)
- 重载此方法以实现替代委派模型。findResource
和findResources
- 重载这些方法以自定义资源加载。
负责从字节数组中实际加载类的 defineClass
方法是 final
以防止重载。在调用 defineClass
之前,需要执行任何自定义行为。
这是一个从字节数组加载特定类的简单:
public class ByteArrayClassLoader extends ClassLoader {
private String classname;
private byte[] classfile;
public ByteArrayClassLoader(String classname, byte[] classfile) {
this.classname = classname;
this.classfile = classfile.clone();
}
@Override
protected Class findClass(String classname) throws ClassNotFoundException {
if (classname.equals(this.classname)) {
return defineClass(classname, classfile, 0, classfile.length);
} else {
throw new ClassNotFoundException(classname);
}
}
}
由于我们只重写了 findClass
方法,所以当调用 loadClass
时,这个自定义类加载器将表现如下。
- 类加载器的
loadClass
方法调用findLoadedClass
来查看此类加载器是否已加载具有此名称的类。如果成功,则生成的Class
对象将返回给请求者。 - 然后
loadClass
方法通过调用loadClass
调用委托给父类加载器。如果父进程可以处理请求,它将返回一个Class
对象,然后将该对象返回给请求者。 - 如果父类加载器无法加载类,则
findClass
会调用我们的覆盖findClass
方法,传递要加载的类的名称。 - 如果请求的名称与
this.classname
匹配,我们调用defineClass
从this.classfile
字节数组加载实际的类。然后返回生成的Class
对象。 - 如果名称不匹配,我们扔
ClassNotFoundException
。