Java类加载器,java类加载
Java类加载器,java类加载
类加载器(class loader)是用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。
基本上所有的类加载器都是 java.lang.ClassLoader类的一个实例。下面详细介绍这个 Java 类。
java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class类的一个实例。
ClassLoader提供了一系列的方法,比较重要的方法如:方法 | 说明 |
---|---|
getParent() | 返回该类加载器的父类加载器。 |
loadClass(String name) | 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。 |
findClass(String name) | 查找名称为 name的类,返回的结果是 java.lang.Class类的实例。 |
findLoadedClass(String name) | 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。 |
defineClass(String name, byte[] b, int off, int len) | 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的。 |
resolveClass(Class<?> c) |
链接指定的 Java 类。 |
java虚拟机中可以安装多个类加载器,系统默认三个主要的类加载器,每个加载器负责加载特定位置的类。
系统默认的三个类加载器之间的父子关系:BootStrap(爷)------ExtClassLoader(父)-----AppClassLoader(子)
注意:类加载器也是java类,但是这些加载器类本身又由谁来加载呢?显然必须有第一个类加载器不是java类,
这个加载器就是BootStrap,它不是一个java类,是直接在虚拟机里面的一个加载器。其他两个加载器都是java类。
BootStrap加载JRE/lib/rt.jar里面的类,ExtClassLoader加载JRE/lib/ext/*.jar里面的类,AppClassLoader加载classpath指定的所有jar或目录里面的类。
第一个类加载器用来加载存储在文件系统上的 Java 字节代码。完整的实现如下
-
public class FileSystemClassLoader extends ClassLoader {
-
-
private String rootDir;
-
-
public FileSystemClassLoader(String rootDir) {
-
this.rootDir = rootDir;
-
}
-
-
protected Class<?> findClass(String name) throws ClassNotFoundException {
-
byte[] classData = getClassData(name);
-
if (classData == null) {
-
throw new ClassNotFoundException();
-
}
-
else {
-
return defineClass(name, classData, 0, classData.length);
-
}
-
}
-
-
private byte[] getClassData(String className) {
-
String path = classNameToPath(className);
-
try {
-
InputStream ins = new FileInputStream(path);
-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
int bufferSize = 4096;
-
byte[] buffer = new byte[bufferSize];
-
int bytesNumRead = 0;
-
while ((bytesNumRead = ins.read(buffer)) != -1) {
-
baos.write(buffer, 0, bytesNumRead);
-
}
-
return baos.toByteArray();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
return null;
-
}
-
-
private String classNameToPath(String className) {
-
return rootDir + File.separatorChar
-
+ className.replace('.', File.separatorChar) + ".class";
-
}
- }
相关文章
- 暂无相关文章
用户点评