类加载器
类加载器(Class Loader)是Java虚拟机(JVM)的一个子系统,负责将类的字节码加载到内存中,并生成对应的Java类对象。类加载器在Java程序运行时动态地加载需要的类文件,使得Java具备了动态加载类和实现动态链接的能力。
常见的类加载器有以下几种:
- 启动类加载器(Bootstrap Class Loader):
○ 是JVM的内置类加载器,负责加载Java的核心类库,如java.lang包中的类。由C++编写,不是Java类,是JVM的一部分。 - 扩展类加载器(Extension Class Loader):
○ 负责加载Java的扩展类库,位于JRE的lib/ext目录下的JAR文件中的类。它的父类加载器是启动类加载器。 - 应用程序类加载器(Application Class Loader):
○ 根据用户自定义的类路径加载类它的父类加载器是扩展类加载器。 - 自定义类加载器(Custom Class Loader):
○ 开发者可以通过继承java.lang.ClassLoader类实现自定义的类加载器。自定义类加载器可以根据特定需求来加载类,比如从网络或数据库中加载类。
Java的类加载器采用了委托模型(Delegation Model),即类加载器在加载类时会首先委托给其父类加载器尝试加载,只有当父类加载器无法加载时,才由当前类加载器自己加载。这样的层级关系可以保证类的加载安全性,避免类的重复加载,同时也方便了类加载器的扩展和定制。
如何打破双亲委派模型
继承ClassLoader类,重写loadClass方法和findClass方法。
public class CustomClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
// 尝试委托给父类加载器加载类
Class<?> loadedClass = super.loadClass(name);
if (loadedClass == null) {
// 如果父类加载器无法加载,尝试自己加载
loadedClass = findClass(name);
}
return loadedClass;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// 实现自己的类加载逻辑,例如从文件或网络中加载类的字节码
byte[] classBytes = loadClassBytes(name);
if (classBytes == null) {
throw new ClassNotFoundException(name);
}
// 调用defineClass方法将字节码转换为类对象
return defineClass(name, classBytes, 0, classBytes.length);
}
private byte[] loadClassBytes(String className) {
// 实现加载类字节码的逻辑,例如从文件或网络中读取字节码数据
// 返回一个包含类字节码的字节数组
return null;
}
public static void main(String[] args) throws Exception {
// 创建自定义类加载器实例
CustomClassLoader customClassLoader = new CustomClassLoader();
// 使用自定义类加载器加载类
String className = "com.example.MyClass"; // 替换成你要加载的类名
Class<?> loadedClass = customClassLoader.loadClass(className);
// 打印加载的类信息
System.out.println("Loaded class: " + loadedClass.getName());
}
}