重写 findClass 方法的核心目的是自定义类的二进制字节码加载逻辑,需继承 ClassLoader、在 findClass 中转换路径、读取字节数组并调用 defineClass,失败时抛 ClassNotFoundException。

在 Java 中重写 ClassLoader 的 findClass(String name) 方法,核心目的是**自定义类的二进制字节码加载逻辑**,而不是直接覆盖 loadClass(避免破坏双亲委派机制)。正确做法是:继承 ClassLoader,重写 findClass,并在其中调用 defineClass 将字节数组转为 Class 对象。
为什么要重写 findClass 而不是 loadClass
loadClass 默认实现已包含双亲委派逻辑(先委托父加载器,失败再调用自己的 findClass)。直接重写 loadClass 容易绕过委派,引发 ClassNotFoundException 或重复定义类等问题。而 findClass 是专为子类定制“如何获取 class 字节码”设计的钩子方法,语义清晰、安全可控。
重写 findClass 的基本步骤
- 继承
java.lang.ClassLoader(通常不直接继承,而是继承URLClassLoader或从头写) - 重写
protected Class<?> findClass(String name) - 在方法内:将类名(如
"com.example.MyClass")转换为资源路径(如"com/example/MyClass.class") - 通过自定义方式读取该路径对应的
byte[](比如从文件、网络、加密包、内存缓存等) - 调用
defineClass(name, byte[], offset, length)返回Class对象 - 若无法找到,抛出
ClassNotFoundException(不能返回 null)
一个简单示例:从指定目录加载 class 文件
假设 class 文件存放在 /tmp/classes/ 目录下:
public class MyClassLoader extends ClassLoader {
private final File classesDir;
public MyClassLoader(File classesDir) {
this.classesDir = classesDir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String path = name.replace('.', '/') + ".class";
File classFile = new File(classesDir, path);
try (FileInputStream fis = new FileInputStream(classFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
int b;
while ((b = fis.read()) != -1) {
baos.write(b);
}
byte[] bytes = baos.toByteArray();
return defineClass(name, bytes, 0, bytes.length);
} catch (IOException e) {
throw new ClassNotFoundException("Class not found: " + name, e);
}
}
}
使用时:
MyClassLoader loader = new MyClassLoader(new File("/tmp/classes"));<br>
Class<?> cls = loader.loadClass("com.example.Hello");
注意事项和常见陷阱
-
defineClass必须传入原始类名(如"java.lang.String"),不能是内部类或数组的规范名(如"[Ljava.lang.String;")——这类需用findLoadedClass或ClassLoader.getSystemClassLoader().loadClass处理 - 确保
name和字节码实际定义的类名一致,否则抛NoClassDefFoundError或SecurityException - 如果类依赖其他类,确保这些类也能被当前或父加载器加载(遵循双亲委派)
- 避免在
findClass中调用loadClass,可能造成无限递归 - 如需热替换或隔离类加载,还需配合重写
loadClass并显式打破委派(慎用)


















