Java类加载器的主要作用是动态的加载和卸载类文件。当程序需要使用某个类时,Java类加载器首先检查该类是否已经被加载到内存中,如果未被加载,那么系统将会根据类的字节码文件形成需要的 Class 对象。
类加载器的工作过程主要包括以下几步:
- 加载:寻找字节流,读入硬盘正常编译后的 .class 文件。
- 连接:主要包括验证、准备以及解析三部分。验证是为了确保 Class 文件的字节流符合实际要求,防止出现安全问题;准备阶段是分配类变量的内存空间;解析阶段就是将符号引用转为直接引用。
- 初始化:这个阶段主要是执行类变量初始的赋值动作,以及执行静态块内部的语句。
在Java中,类加载器的实现主要有以下三种:
- 启动类加载器(BootStrap ClassLoader):这个加载器负责将存放在<JAVA_HOME>/lib目录中的,或者被-Xbootclasspath选项指定的路径中的,并且满足一定条件的类库加载到 JVM 的内存中。启动类加载器无法被Java程序直接引用。
- 扩展类加载器(Extension ClassLoader):这个加载器负责加载<JAVA_HOME>/lib/ext目录中的,或者由系统变量-Djava.ext.dirs指定的路径中的所有类库,开发者可以直接使用标准扩展类加载器。
- 应用程序类加载器(Application ClassLoader):这个加载器负责加载用户类路径(ClassPath)上所指定的类库,开发者也可以直接使用这个加载器。
Java 类加载器的特点:
- 双亲委派模型:当一个类收到类加载请求,它会首先请求为它的父类加载器进行加载,直到应用程序类加载器。如果父类加载器可以完成加载请求,就成功返回;只有当父类加载器无法完成此加载请求时,才由它自己来加载。
- 可见性原则:子加载器的命名空间中举行父加载器的命名空间,即由父类加载器加载的类能被子类加载器看见;但父加载器的命名空间中看不见子加载器的命名空间。
- 单一性原则:由父类加载器加载的类能被子类共享,即加载一个类时,首先尝试使用父类加载器进行加载,所以被父加载器加载的同一类不会被子加载器加载一次。
最后,让我们看看类加载器的双亲委派机制。这是Java类加载器最重要的安全机制之一。
每一个类加载器都有一个“父类加载器”,当加载一个类的时候,它首先将加载任务委托给自己的父类加载器,依次向上,如果父类加载器可以完成类加载任务,就成功返回;
只有父类加载器无法完成此加载任务时,才由自己来完成。这种机制可以保证对Java核心库的保护,因为核心的类库都由Bootstrap ClassLoader 加载,自定义的类加载器不会覆盖核心类。
类加载器是Java中的一个重要组成部分,它负责加载类到JVM中。Java提供了三种默认的类加载器,每种类加载器都有其特定的加载范围。
双亲委派机制是Java类加载的一个重要安全机制,可以防止核心类库被篡改。 同时,也可以自定义类加载器,用于一些特殊的需求,如热替换等。