ClassLoader在Java中有着非常重要的作用,它主要工作在Class装载的加载阶段,其主要作用是从系统的外部获取Class二进制数据流。
1、认识ClassLoader
ClassLoader是Java的核心组件,所有的Class都是由ClassLoader进行加载。因此,ClassLoader在整个装载阶段,只能影响到类的加载,而无法通过ClassLoader去改变类的连接和初始化行为。
2、ClassLoader分类
Java虚拟机会创建3类ClassLoader为整个应用程序服务。分别是:BootStrap ClassLoader(启动类加载器)、Extension ClassLoader(扩展类加载器)和AppClassLoader(应用类加载器,也称为系统类加载器),此外,每一个应用程序还可以拥有自定义的ClassLoader,扩展Java虚拟机获取Class数据的能力。
从ClassLoader的层次自顶往下为启动类加载器、扩展类加载器、应用类加载器和自定义类加载器。其中应用类加载器的双亲为扩展类加载器,扩展类加载器的双亲为启动类加载器,
在这些ClassLoader中启动类加载器最为特别,它是完全由C代码实现的,并且在Java中没有对象与之对应。系统的核心类就是由启动类加载器进行加载的,它是虚拟机的核心组件。
在虚拟机设计中,使用这种分散的ClassLoader去装载类是有好处的,不同层次的类可以由不同的ClassLoader加载,从而进行划分,有助于系统的模块化设计。
一般:
启动类加载器负责加载系统的核心类,比如rt.jar中的Java类。
扩展类加载器负责用于加载%JAVA_HOME%/lib/ext/*.jar的Java类。
应用类加载器负责加载用户类,用户程序的类。
自定义类加载器用于加载一些特殊途径的类,一般也是用户类。
ClassLoader的双亲委托模式
系统中的ClassLoader在协调工作时,默认会使用双亲委托模式。即在类加载的时候,系统会判断当前类时候已经被加载,如果已经被加载,就会直接返回可用的类,否则就会尝试加载,
在加载时,会首先请求双亲处理,如果双亲请求失败,则会自己加载。
注意:判断类是否加载时,应用类加载器会顺着双亲路径往上判断,直到启动类加载器。但是启动类加载器不会往下询问,这个委托路线是单向的。
双亲委托模式的弊端
类加载检测顺序:
虽然各个ClassLoader的任务是明确的,但是顶层的ClassLoader 无法访问底层的ClassLoader所加载的类。
设置在线程中的上下文加载器,这样即使是在启动类加载器中的类也可以通过这种方式访问应用类加载器中的类。