Java中的ClassLoader核心知识点
时间:2021-11-18

本文整理了基于JDK8的ClassLoader核心知识点,包括JVMClassLoader类型、ClassLoader执行顺序、父加载器概念、父母任命机制和定制加载器。

整理Java中ClassLoader的核心知识点。

JDK和JRE的作用。

●JDK提供java编程环境,包括编译调试的环境功能,包括JRE(JDK目录中的JRE是专用JRE,安装后与JDK同目录的JRE是公用JRE)。JDK专用JRE通常在开发过程中运行,而公共JRE通常在运行外部程序时运行,实现了不同分工的JRE负责各自范围的内容。

●JRE为JAVA程序运行提供了必要的环境平台。

JAVAHOME,PATH,CLASPATH。

●JAVAHOME:JDK安装的位置路径,如:D:\ProgramFiles\Java\jdk1.8.0_241。

●PATH:配置后运行bin中的命令不需要完成全路径,如java和javac命令可以在任何位置运行,%JAVA_HOME%\bin;

●CLASPATH:指向jar包路径%JAVA_HOME%\lib;

类型加载器。

JVM中有三种Classloader:

●BootstrapClassloader启动类(或根类)加载器。

●ExtentionClassloader扩展类加载器。

●Appclassloader应用加载器。

整理Java中ClassLoader的核心知识点。

(1)BootstrapClassloader。

BootstrapClasloader顶级类加载器,主要加载核心类库%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar、class文件等。

(2)ExtentionClassLoader。

Extentionclassloader扩展类加载器,主要加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。

(3)Appclassloader。

Appclassloader又称SystemAppclass加载当前应用的classpath的所有类别。

类加载器的执行顺序。

除了启动加载器(BootstrapClassloader)外,扩展加载器和应用加载器都是通过类sun.misc.Launcher初始化的,而Launcher由启动加载器加载。Launcher相关代码如下:

加载顺序:BootstrapClassloder>ExtentionClassloader>AppClassloader。

父加载器概念。

Appclassloader和Extclassloader都继承了URLclassloader。每个类加载器都有一个父加载器(注:父加载器和父加载器是两个不同的概念),父加载器可以通过getParent()获得。

●Appclassloader的父加载器是Extclassloader。

●Extclassloader的父加载器是Bootstrapclassloader(以上代码输出Extclassloader是null,因为Bootstrapclasloader本身不是Java)

●BootstrapClassloader是由C/C++编写的,它本身就是虚拟机的一部分,所以它不是JAVA类,也就是说,它不能在Java代码中获得它的引用。JVM启动时,rt.jar等核心jar包中的class文件由Bootstrap加载器加载,之前的int.class、string.class由它加载。然后,我们之前分析过JVM初始化sun.misc.Launcher,创建Extensionclassloader和Appclassloader实例。并将Extclassloader设置为Appclassloader的父加载器。Bootstrap没有父加载器,但它可以作为Classloader的父加载器。

双亲委派

父母指定的模型:当一个类加载器收到类加载请求时,它将首先要求其父类加载器加载并依次递归。当父类加载器找不到此类时(根据类的全限名称),子类加载器将尝试加载。

为什么用双亲委派模型?

为了保证Java核心库的类型安全,双亲委派模型。所有Java应用程序至少需要引用java.lang.Object类别,这些类别在运行时加载到Java虚拟机中。如果加载过程由自定义加载器完成,可能会有多个版本的java.lang.Object类,这些类不兼容。

通过父母指定的模型,Java核心库的加载工作由启动加载器统一完成,确保Java应用程序使用相同版本的Java核心库,相互兼容。

自定义加载器。

无论是Bootstrapclassloader还是Extclassloader等,这些类型的加载器只加载指定目录下的jar包或资源。如需动态加载,如从指定目录中加载class文件,则可通过自定义加载器实现。

自定义加载器只需继承java.lang.classloader类,然后重写findclass(stringname)方法,指示如何在方法中获取类字节码流。要破坏双亲委派规范,还需要重写loadClass方法(实现双亲委派的具体逻辑)。但不建议这样做。


标签: 知识应用代码