类与类加载器
1 | 虚拟机设计团队把类加载阶段中的 "通过一个类的全限定名来获取描述此类的二进制字节流" 这个动作放到 Java 虚拟机外部去实现,以便让应用程序自己决定如何 |
类加载器 虽然只用于实现类的加载动作,但它在Java 程序中起到的作用却远远不限于类加载阶段。
对于任意一个类,都需要 由 加载它的类加载器 和 这个类本身一同确立其在 Java 虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。 两个类来自同一个 Class 文件,被同一个虚拟机加载,只要加载它们的类加载器不同,则这两个类必定不相等。
双亲委派模型
从 Java 虚拟机的角度来讲,只存在两种不同的类加载器:
1. 启动类加载器(Bootstrap ClassLoader), 这个类加载器使用 C++ 实现的(这里只限于 HotSpot ,MRP/Maxine 等虚拟机本身都是由 Java 编写的) , 是**虚拟机自身的一部分**。
2. 所有其他类加载器,都由 Java 语言实现,独立于 **虚拟机外部**,并且全都继承于抽象类 java.lang.ClassLoader
类加载器的分类
类加载器可以分得更细致一些,大部分 Java 程序都使用到以下 3 种系统提供的类加载器。
- 启动类加载器(Bootstrap ClassLoader)
- 负责将存放在 <JAVA_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,并且是 虚拟机识别的(仅按照文件名识别,如 rt.jar ,名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。
- 启动类加载器无法被 Java 程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那么直接使用 null 代替即可。
- 扩展类加载器(Extension ClassLoader)
- 这个加载器由 sun.misc.Launcher$ExtClassLoader 实现,它负责加载 <JAVA_HOME>\lib\ext 目录中的,或者被 java.ext.dirs 系统变量所指定的路径中的所有类库,开发者可以直接使用
- 应用程序类加载器(Application ClassLoader)
- 这个类加载器由 sun.misc.Launcher$AppClassLoader 实现。由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,所以一般也称它为系统类加载器。
- 它负责加载用户类路径(ClassPath) 上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
双亲委派模型并不是强制性的约束模型。