Java中的类加载器层次结构
Java中的类加载器层次结构主要包括以下几种类加载器,它们之间存在一定的父子关系,这种关系主要基于双亲委派模型:
引导类加载器(Bootstrap ClassLoader):
- 这是最顶层的类加载器,由C++编写实现,不继承自
java.lang.ClassLoader
。 - 它主要负责加载Java的核心库,这些库通常位于
JAVA_HOME/jre/lib/rt.jar
(或对应JDK版本的路径)中,以及其他由JVM指定的路径。 - 由于是原生代码实现,因此在Java中无法直接获取到它的实例。
- 这是最顶层的类加载器,由C++编写实现,不继承自
扩展类加载器(Extension ClassLoader):
- 由Java编写,继承自
java.lang.ClassLoader
。 - 主要负责加载Java的扩展库,这些库位于
JAVA_HOME/jre/lib/ext
(或java.ext.dirs
系统属性指定的路径)中。 - 它被引导类加载器所加载。
- 由Java编写,继承自
系统类加载器(System ClassLoader)或应用程序类加载器(Application ClassLoader):
- 同样由Java编写,继承自
java.lang.ClassLoader
。 - 它负责加载用户类路径(classpath)上所指定的类库,包括开发者自己编写的Java类。
- 它被扩展类加载器所加载。
- 同样由Java编写,继承自
自定义类加载器:
- 开发人员可以通过继承
java.lang.ClassLoader
类来实现自己的类加载器,以满足特定的需求。 - 自定义类加载器可以加载指定路径下的类,或者通过特殊的方式加载类,比如从网络加载。
- 开发人员可以通过继承
双亲委派模型
双亲委派模型是Java类加载器在加载类时采用的一种机制,它确保了类的加载过程具有安全性和一致性。具体来说,当某个类加载器需要加载一个类时,它会首先尝试将这个任务委派给它的父类加载器去完成,依次递归,直到引导类加载器。只有当父类加载器无法完成这个加载任务时,子类加载器才会尝试自己去加载。
双亲委派模型的主要优点包括:
- 避免重复加载:由于每个类只会被加载一次,避免了重复加载相同的类,从而提高了程序执行效率。
- 保证安全性:通过优先委派给父加载器进行加载,可以避免恶意代码通过自定义的类加载器来劫持JVM,从而保证了程序的安全性。
- 统一管理:由于所有的类的加载都由顶层的启动类加载器加载,因此可以统一管理类的加载,从而更好地进行内存管理和JVM优化。
工作流程:
- 当一个类加载器接收到一个类加载请求时,它首先检查自己是否已经加载过这个类。
- 如果没有加载过,它会将这个请求委派给它的父类加载器。
- 父类加载器同样会先检查自己是否已经加载过这个类,如果没有,则继续向上委派,直到引导类加载器。
- 如果引导类加载器也无法加载这个类,那么类加载请求会依次向下传递,直到某个子类加载器能够加载这个类为止。
- 如果所有的类加载器都无法加载这个类,则抛出
ClassNotFoundException
。
这种机制确保了Java核心库的类型安全,避免了用户自定义的类与Java核心库中的类发生冲突。