JVM学习-类加载器

55 阅读3分钟

:什么是类加载器

1.类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。 类加载器只参与加载过程中的字节码获取并加载到内存这一部分。

:类加载器分类(jdk8及之前)

  • java虚拟机底层代码源码实现的:保证java程序运行中基础类被正确地加载,比如java.lang.String,确保其可靠性。启动类加载器
  • java代码中实现的:继承自抽象类ClassLoader。扩展类加载器,应用类加载器

:启动类加载器

  • 启动类加载器(Bootstrap ClassLoader)是由Hotspot虚拟机提供的、使用C++编写的类加载器。
  • 默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等
  • 通过启动类加载器去加载用户jar包:
    • 放入jre/lib下进行扩展:不推荐,尽可能不要去更改JDK安装目录中的内容,会出现即时放进去由于文件名不匹配的问题也不会正常地被加载
    • 使用参数进行扩展:推荐,使用-Xbootclasspath/a:jar包目录/jar包名 进行扩展

:扩展类加载器和应用类加载器

  • 扩展类加载器和应用程序类加载器都是JDK中提供的、使用Java编写的类加载器

  • 它们的源码都位于sun.misc.Launcher中,是一个静态内部类。继承自URLClassLoader。具备通过目录或者指定jar包将字节码文件加载到内存中。

image.png

扩展类加载器:
  • 默认加载Java安装目录/jre/lib/ext下的类文件。
  • 通过扩展类加载器去加载用户jar包:
    • 放入/jre/lib/ext下进行扩展:不推荐,尽可能不要去更改JDK安装目录中的内容
    • 使用参数进行扩展:推荐,使用-Djava.ext.dirs=jar包目录 进行扩展,这种方式会覆盖掉原始目录,可以用;(windows):(macos/linux)追加上原始目录
应用类加载器:
  • 加载classpath下的类文件和应用使用的类

:双亲委派机制

  • 双亲委派机制指的是:自底向上查找是否加载过,再由顶向下进行加载。
  • 作用:
    • 保证类加载的安全性通过双亲委派机制,让顶层的类加载器去加载核心类,避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。
    • 避免重复加载,双亲委派机制可以避免同一个类被多次加载,上层的类加载器如果加载过类,就会直接返回该类,避免重复加载。

image.png

:打破双亲委派机制

1.自定义类加载器
  • 继承ClassLoader,重写loadClass()方法
  • 自定义加载器的父加载器是默认是应用类加载器
2.线程上下文类加载器(使用了SPI机制+线程上下文类加载器)
  • JDBC案例:DriverManager属于rt.jar是启动类加载器加载的。而用户jar包中的驱动需要由应用类加载器加载,这就违反了双亲委派机制。

image.png

3.OSGi模块化
  • OSGi模块化框架。它存在同级之间的类加载器的委托加载。

image.png

JDK9之后的类加载器

  • 扩展类加载器被替换成了平台类加载器(Platform Class Loader)。
  • 平台类加载器遵循模块化方式加载字节码文件,所以继承关系从URLClassLoader变成了 BuiltinClassLoader,BuiltinClassLoader实现了从模块中加载字节码文件。

image.png