实现自定义 classLoader

每个自定义加载器必须直接或间接扩展 java.lang.ClassLoader 类。主要的扩展点是以下方法:

  • findClass(String) - 如果类加载器遵循类加载的标准委托模型,则重载此方法。
  • loadClass(String, boolean) - 重载此方法以实现替代委派模型。
  • findResourcefindResources - 重载这些方法以自定义资源加载。

负责从字节数组中实际加载类的 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 时,这个自定义类加载器将表现如下。

  1. 类加载器的 loadClass 方法调用 findLoadedClass 来查看此类加载器是否已加载具有此名称的类。如果成功,则生成的 Class 对象将返回给请求者。
  2. 然后 loadClass 方法通过调用 loadClass 调用委托给父类加载器。如果父进程可以处理请求,它将返回一个 Class 对象,然后将该对象返回给请求者。
  3. 如果父类加载器无法加载类,则 findClass 会调用我们的覆盖 findClass 方法,传递要加载的类的名称。
  4. 如果请求的名称与 this.classname 匹配,我们调用 defineClassthis.classfile 字节数组加载实际的类。然后返回生成的 Class 对象。
  5. 如果名称不匹配,我们扔 ClassNotFoundException