(class loader)机制来动态加载.class文件或JAR包中的类。类加载器是Java运行时环境的一部分,负责将.class文件转换为JVM可以理解和执行的java.lang.Class对象。
类加载器的主要类型:
启动类加载器(Bootstrap Class Loader):
- 负责加载JDK的核心库,如java.lang.Object。
扩展类加载器(Extension Class Loader):
- 负责加载JDK的扩展目录中的类库。
系统类加载器(System Class Loader):
- 负责加载用户类路径(Classpath)上的类库。
自定义类加载器(User-defined Class Loader):
- 开发者自定义的类加载器,用于实现特定的类加载需求。
类加载过程:
加载(Loading):
- 读取.class文件的二进制数据,并创建一个java.lang.Class对象。
验证(Verification):
- 确保加载的类信息符合JVM规范,没有安全问题。
准备(Preparation):
- 分配静态变量的内存,并设置默认初始值。
解析(Resolution):
- 将常量池中的符号引用转换为直接引用。
初始化(Initialization):
- 执行类构造器
<clinit>()
方法,初始化静态变量。
- 执行类构造器
如何使用类加载器:
使用系统类加载器:
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); Class<?> myClass = systemClassLoader.loadClass("com.example.MyClass");
使用URLClassLoader加载网络资源:
URL url = new URL("http://example.com/MyClass.class"); URLClassLoader customClassLoader = new URLClassLoader(new URL[]{ url}); Class<?> myClass = customClassLoader.loadClass("com.example.MyClass");
自定义类加载器:
public class MyClassLoader extends ClassLoader { private String path; public MyClassLoader(String path) { this.path = path; } @Override public Class<?> findClass(String name) throws ClassNotFoundException { // 实现类的加载逻辑 byte[] b = loadByteCode(name); return defineClass(name, b, 0, b.length); } private byte[] loadByteCode(String className) { // 从自定义路径加载.class文件 // 这里只是一个示例,需要根据实际情况实现 return null; } }
使用自定义类加载器加载类:
MyClassLoader myClassLoader = new MyClassLoader("/path/to/classes"); try { Class<?> myClass = myClassLoader.loadClass("com.example.MyClass"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
代码示例:
这是一个简单的自定义类加载器示例,用于从指定目录加载类:
import java.io.*;
public class DirectoryClassLoader extends ClassLoader {
private String directoryPath;
public DirectoryClassLoader(String directoryPath) {
this.directoryPath = directoryPath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
String path = directoryPath + File.separator + name.replace('.', File.separatorChar) + ".class";
byte[] b = new byte[1024];
FileInputStream fis = new FileInputStream(path);
DataInputStream dis = new DataInputStream(fis);
int i, count = 0;
while ((i = dis.read()) != -1) {
b[count++] = (byte) i;
}
dis.close();
return defineClass(name, b, 0, count);
} catch (IOException e) {
throw new ClassNotFoundException(name);
}
}
public static void main(String[] args) {
try {
DirectoryClassLoader dcl = new DirectoryClassLoader("/path/to/classes");
Class<?> c = dcl.loadClass("com.example.MyClass");
Object o = c.newInstance();
System.out.println("Class loaded and instantiated successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}
}