一、类加载器(ClassLoader)
1.1 什么是类加载器
Java的类加载器是Java虚拟机(JVM)的重要组成部分,它的主要作用是动态地将Java类加载到JVM中,以便在运行时使用这些类。Java类加载器通常是由JVM的实现者提供的,但用户也可以通过扩展ClassLoader类来定义自己的类加载器。
Java类加载器采用了双亲委派模型,即在加载一个类时,会先由父类加载器尝试加载该类,如果父类加载器无法加载,则交给子类加载器去尝试加载。这样可以确保Java类的唯一性,同时也可以防止Java类库被恶意篡改。
Java类加载器可以分为三个层次:启动类加载器、扩展类加载器和应用程序类加载器。启动类加载器是JVM的一部分,用于加载Java核心类库,扩展类加载器用于加载JVM扩展的一些API,而应用程序类加载器则用于加载应用程序中的类。
1.2 类加载器的三个层次
- 启动类加载器
启动类加载器(Bootstrap ClassLoader)是Java虚拟机的一部分,是用本地代码实现的类加载器,主要用于加载JRE/lib目录下的核心Java类库,如rt.jar、charsets.jar等。启动类加载器是Java虚拟机最顶层的类加载器,它没有父类加载器。
启动类加载器使用C++编写,因此无法在Java代码中获取到它的引用。启动类加载器加载的类不受限于类路径的限制,因为它在Java虚拟机启动时就已经被加载了。
- 扩展类加载器
扩展类加载器(Extension ClassLoader)是由Java代码实现的类加载器,它的父类加载器是启动类加载器。扩展类加载器用于加载Java扩展API,这些API通常存放在JRE/lib/ext目录下,如jconsole.jar、jmxremote.jar等。
扩展类加载器在Java虚拟机启动时会被创建,它的类加载路径可以通过系统属性java.ext.dirs来指定。如果要使用自定义的扩展类加载器,也可以通过设置java.system.class.loader系统属性来指定。
- 应用程序类加载器
应用程序类加载器(Application ClassLoader),也称为系统类加载器(System ClassLoader),是Java虚拟机中最常用的类加载器,它的父类加载器是扩展类加载器。应用程序类加载器用于加载应用程序中的类,通常存放在CLASSPATH环境变量或者-cp命令指定的目录下。
当Java虚拟机需要加载一个类时,会先让应用程序类加载器尝试加载该类,如果应用程序类加载器无法加载,则会依次由其父类加载器进行加载,直到启动类加载器为止。
如果应用程序类加载器的父类加载器无法找到某个类,应用程序类加载器也无法加载该类,因为Java类加载器采用双亲委派模型,即父类加载器优先委派给子类加载器进行加载。
- 其他
类加载器可以通过getClassLoader()方法获取到:
例如:
public class TestClassLoader {
public static void main(String[] args) {
System.out.println(TestClassLoader.class.getClassLoader());
System.out.println(TestClassLoader.class.getClassLoader().getParent());
System.out.println(TestClassLoader.class.getClassLoader().getParent().getParent());
}
}
结果:
jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
jdk.internal.loader.ClassLoaders$PlatformClassLoader@58ceff1
null
由此可见应用程序类加载器和扩展类加载器都可以被获取到,而启动类加载器因为是由C++所编写的所以获取时为空;
加载特性:
自顶向下尝试加载,自底向上检查是否加载成功;