重写findClass方法是为了在不破坏双亲委派模型的前提下实现自定义类加载逻辑,如从网络、数据库或加密文件加载字节码,并通过defineClass将字节码转为Class对象。

在Java中,重写findClass方法通常是为了实现自定义类加载逻辑,常见于继承ClassLoader的子类。默认情况下,ClassLoader的loadClass方法会调用findClass来查找并加载类。JVM推荐的做法是:让父类加载器先尝试加载类,只有在父类加载器无法完成时,才由当前类加载器通过重写的findClass方法来加载。
为什么要重写 findClass 方法?
findClass 是 ClassLoader 中的一个受保护方法,设计初衷就是让开发者在自定义类加载器时重写它。这样可以确保双亲委派模型不被破坏,同时又能灵活控制类的获取方式,比如从网络、数据库、加密文件等来源加载字节码。
如何正确重写 findClass
以下是实现步骤和示例:
- 继承
ClassLoader或更常用的URLClassLoader(如果不需要完全自定义) - 重写
findClass(String name)方法 - 在方法中根据类名获取字节码数据(byte[])
- 使用
defineClass()将字节码转换为Class对象
public class CustomClassLoader extends ClassLoader {
private String classPath;
public CustomClassLoader(String classPath) {
this.classPath = classPath;
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
byte[] classData = loadClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
}
return defineClass(name, classData, 0, classData.length);
}
private byte[] loadClassData(String className) {
// 将类名转换为路径
String fileName = classPath + File.separatorChar +
className.replace('.', File.separatorChar) + ".class";
try (InputStream is = new FileInputStream(fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
int ch;
while ((ch = is.read()) != -1) {
baos.write(ch);
}
return baos.toByteArray();
} catch (IOException e) {
return null;
}
}
}
使用方式:
在原有基础上进行了较大改动进行了代码重写,页面结构和数据库结构均作了优化,基本功能: 1. 精美flash导入页面; 2. 产品发布,支持一级分类; 3. 公司简介、售后服务、联系我们,可进行后台管理; 4. 也可以照“公司简介”的方法增加其他内容,如企业文化、企业荣誉... 5. 采用eWebEditor是网站后台具有强大的编辑功能; 初始帐号: admin 初始密码: admin888
立即学习“Java免费学习笔记(深入)”;
CustomClassLoader loader = new CustomClassLoader("myclasses");
Class> clazz = loader.loadClass("com.example.Hello");
Object obj = clazz.newInstance();
注意事项
重写时需注意以下几点:
- 不要重写
loadClass方法,除非你明确要打破双亲委派机制。否则应只重写findClass -
defineClass是ClassLoader提供的方法,用于将字节数组转为 Class 实例,不能直接调用,必须在findClass或其调用链中使用 - 确保类名与字节码内容一致,否则可能引发
NoClassDefFoundError或安全异常 - 对于复杂的类加载场景(如隔离、热部署),可结合缓存、命名空间管理等机制
基本上就这些。重写 findClass 是实现自定义类加载的核心方式,关键在于提供正确的字节码并交给 defineClass 处理,同时保持类加载的委托机制不变。不复杂但容易忽略细节。










