当前位置: 首页 > news >正文

JVM之【类加载系统】

目录

前言

类加载过程

类加载

执行过程

加载阶段

连接阶段

初始化阶段

类加载器

BootstrapClassLoader

ExtClassLoader

AppClassLoader

类加载器之间的关系

双亲委派机制

核心思想

好处

源码分析

类加载器之间的父子层级关系

双亲委派的体现


前言

上文中提到,Java源文件通过前端编译器生成.class字节码文件,字节码文件通过JVM中的类加载系统加载进内存再交由执行引擎处理,本文主要介绍类加载系统

类加载过程

类加载

当JVM需要用到某个类时,会加载它的.class文件,加载之后会创建对应的Class对象

执行过程

整个执行过程分为阶段:加载阶段、连接阶段、初始化阶段

加载阶段

通过完全限定名查找class文件二进制数据并加载进内存的过程,可以划分为三步

  1. 通过完全限定名定位到.class文件,并获取其二进制字节流数据
  2. 字节流的静态存储结构变为运行时数据结构
  3. 堆空间中创建一个Class对象,作为程序访问其数据的入口

连接阶段

分为验证、准备、解析三步,其中解析可能会在初始化之后执行

  1. 验证:检测class字节流数据是否符合虚拟机的要求,确保不会危害虚拟机自身的安全
  2. 准备:为类中声明的静态变量分配内存空间,并将其初始化为默认值
  3. 解析:把类中对常量池内的符号引用转化为直接引用的过程

初始化阶段

执行<clinit>(),对类的静态变量赋予指定的值(声明时指定的值或静态代码块赋予的值)

类加载器

JVM提供了三种类加载器,分别为BootstrapClassLoader、ExtClassLoader、AppClassLoader;当然也可以自定义实现类加载器

BootstrapClassLoader

是用C++实现的一种类加载器,是JVM的一部分,负责将如下两种位置下的类库加载到内存

  1. <JAVA_HOME>\lib
  2. -Xbootclasspath 指定

ExtClassLoader

是由sun公司实现的,位于sun.misc.Launcher中的一个静态内部类

package sun.misc;
// ...public class Launcher {// ...// 扩展类加载器ExtClassLoaderstatic class ExtClassLoader extends URLClassLoader {// ...}// ...
}

负责将如下两种位置下的类库加载到内存

  1. <JAVA_HOME>\lib\ext
  2. -Djava.ext.dir 指定

AppClassLoader

也是由sun公司实现,位于sun.misc.Launcher中的一个静态内部类,负责将类路径下的类库加载到内存

package sun.misc;
// ...public class Launcher {// ...// 应用程序类加载器AppClassLoaderstatic class AppClassLoader extends URLClassLoader {// ...}// ...
}

类加载器之间的关系

BootstrapClassLoader是在JVM启动时初始化的,负责加载ExtClassLoader,并将ExtClassLoader的父加载器设置为BootstrapClassLoader;接着BootstrapClassLoader加载AppClassLoader,并将AppClassLoader的父加载器设置为ExtClassLoader,自定义类加载器的父加载器为AppClassLoader

package classloader;public class CustomClassLoader extends ClassLoader {public static void main(String[] args) {CustomClassLoader customClassLoader = new CustomClassLoader();System.out.println("自定义类加载器:" + customClassLoader);ClassLoader loader = customClassLoader.getParent();System.out.println("自定义类加载器的父加载器:" + loader);loader = loader.getParent();System.out.println("AppClassLoader的父加载器:" + loader);loader = loader.getParent();System.out.println("ExtClassLoader的父加载器:" + loader);}
}

BootstrapClassLoader是由C++实现的,所以获取的是null

双亲委派机制

核心思想

类加载器从上至下为:BootstrapClassLoader -> ExtClassLoader -> AppClassLoader

  • 自下而上检查类是否已经被加载
  • 从上至下尝试加载类

好处

  1. 避免一个类在不同层级的类加载器重复加载
  2. 保障Java核心类的安全性,如通过网络传输一个java.lang.String类,需要被加载时,通过双亲委派机制最终找到BootstrapClassLoader后,发现该类已经被加载从而不会加载传输过来的java.lang.String类,直接返回BootstrapClassLoader加载的String.class,有效防止Java核心API被篡改

源码分析

类加载器之间的父子层级关系

类加载器之间的父子层级关系体现在Launcher类的无参构造器

package sun.misc;public class Launcher {// ...private ClassLoader loader;// ...// 无参构造器public Launcher() {ExtClassLoader var1;try {// 实例化ExtClassLoadervar1 = Launcher.ExtClassLoader.getExtClassLoader();} catch (IOException var10) {throw new InternalError("Could not create extension class loader", var10);}try {// 实例化AppClassLoader,并将ExtClassLoader作为其父加载器this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);} catch (IOException var9) {throw new InternalError("Could not create application class loader", var9);}// 将AppClassLoader作为线程上下文类加载器Thread.currentThread().setContextClassLoader(this.loader);// ...}static class AppClassLoader extends URLClassLoader {final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {// ...// 传过来的var0作为parentreturn new AppClassLoader(var1x, var0);}});}AppClassLoader(URL[] var1, ClassLoader var2) {// var2作为parentsuper(var1, var2, Launcher.factory);this.ucp.initLookupCache(this);}// ...}// ExtClassLoader,单例模式的体现static class ExtClassLoader extends URLClassLoader {private static volatile ExtClassLoader instance;public static ExtClassLoader getExtClassLoader() throws IOException {if (instance == null) {Class var0 = ExtClassLoader.class;synchronized(ExtClassLoader.class) {if (instance == null) {instance = createExtClassLoader();}}}return instance;}private static ExtClassLoader createExtClassLoader() throws IOException {try {return (ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction<ExtClassLoader>() {public ExtClassLoader run() throws IOException {File[] var1 = Launcher.ExtClassLoader.getExtDirs();int var2 = var1.length;for(int var3 = 0; var3 < var2; ++var3) {MetaIndex.registerDirectory(var1[var3]);}return new ExtClassLoader(var1);}});} catch (PrivilegedActionException var1) {throw (IOException)var1.getException();}}// ...}
}

双亲委派的体现

双亲委派模型体现在ClassLoader类中的loadClass方法

package java.lang;public abstract class ClassLoader {// ...protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 通过完全限定名查看自己是否已经加载过Class<?> c = findLoadedClass(name);// 如果自己没有加载过if (c == null) {long t0 = System.nanoTime();try {// 如果父加载器不为空,就将类加载请求委托给父加载器if (parent != null) {c = parent.loadClass(name, false);} else {// 父加载器为空就代表当前类加载器为ExtClassLoader,就将类加载请求委托给BootstrapClassLoaderc = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// ...// 父加载器加载失败时,调用该方法完成类加载c = findClass(name);// ...}}// 加载时是否需要解析if (resolve) {resolveClass(c);}// 返回加载后生成的Class对象return c;}}// ...// 该方法是留给子类重写的protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name);}// ...
}
http://www.dtcms.com/a/347954.html

相关文章:

  • 【Qt开发】常用控件(六)
  • Golang云端编程深度指南:架构本质与高阶实践
  • Flink Slot 不足导致任务Pending修复方案
  • 互联网大厂Java面试实录:从Spring到微服务的全面考察
  • 【软件安全】ARM64、x86、32 位与 64 位架构的区别、定义、应用背景
  • 个人搭建小网站教程(云服务器Ubuntu版本)
  • 【数据结构】二叉树的顺序存储、堆的实现及其应用:堆排序与Top-K问题
  • 以国产IoTDB为代表的主流时序数据库架构与性能深度选型评测
  • kanass V1.1.4版本发布,支持Mysql数据库、ubuntu安装与Mantis数据导入
  • Thonny+MicroPython搭建ESP32芯片开发环境
  • 代码性能测试——benchmark库
  • Elasticsearch Ruby 客户端故障排查实战指南
  • AI与SEO关键词协同优化
  • DBeaver连接SQL Server集成认证问题解决方案
  • xxl-job 启动后导致pod内存使用率持续增加
  • 从 Unity UGUI 到 Unreal UMG 的交互与高效实践:UI 事件、坐标系适配与性能优化
  • MATLAB 与 Simulink 联合仿真:控制系统建模与动态性能优化
  • C#_gRPC
  • RabbitMQ--消费端异常处理与 Spring Retry
  • 阿里云拉取dockers镜像
  • 在JavaScript中,比较两个数组是否有相同元素(交集)的常用方法
  • 今日科技热点 | AI加速创新,5G与量子计算引领未来
  • wpf之DockPanel
  • 3D打印机管理后台与RabbitMQ集成的业务场景
  • RabbitMQ面试精讲 Day 29:版本升级与平滑迁移
  • 【图像处理基石】基于 Python 的图像行人删除技术:实现街景无干扰化处理
  • 性能比拼: .NET (C#) vs. Fiber (Go)
  • Kaggle项目:一次 Uber 出行数据分析的完整思路
  • 高空作业安全监控难题突破!陌讯自适应识别算法实现安全带穿戴检测准确率↑93%
  • 深度学习——详细教学:神经元、神经网络、感知机、激活函数、损失函数、优化算法(梯度下降)