画图学JVM (四) 02 类加载子系统

一、知识结构

在这里插入图片描述

二、类加载子系统

2.1 JVM 结构

在这里插入图片描述

2.2 类加载子系统的作用

在这里插入图片描述Java虚拟机把描述类的数据从Class文件加载到内存, 并对数据进行校验、 转换解析和初始化, 最终形成可以被虚拟机直接使用的 Java 类型, 这个过程被称作虚拟机的类加载机制。

2.3 Class 对象 “相等”

2.3.1 相等定义

包括代表类的 Class 对象的 equals() 方法、isAssignableFrom() 方法、 isInstance() 方法的返回结果, 也包括了使用 instanceof 关键字做对象所属关系判定等各种情况

2.3.2 两个必要条件

  • Class 完整名称必须相同, 包括包名
  • 加载这个类的类加载器必须相同

三、类加载过程

  • 类加载阶段
    在这里插入图片描述类加载阶段包括:加载、验证、准备、解析和初始化

  • 类加载流程
    在这里插入图片描述

3.1 加载阶段

3.1.1 作用

  • 通过一个类的全限定名加载此类的二进制字节流
  • 将这个字节流所代表的静态存储结构转化为方法区运行时数据结构
  • 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的访问接口

3.1.2 加载方式

  • 文件系统
    • 直接加载
    • zip 压缩包读取, 成为日后 war、jar 的基础
    • 由其他文件生成: 典型的 JSP应用
    • 从加密文件中获取, 典型的防 class 文件被反编译的保护措施
  • 通过网络获取,如 web Applet
  • 运行时计算生成, 使用的最多的是:动态代理
  • 从专用的数据库中提取, 比较少见

3.2 连接阶段

连接又分为验证、准备和解析三个子过程

3.2.1 验证

  • 确定 Class 文件流符合 JVM 要求,保证被加载类的正确性,不会危害虚拟机的安全
  • 主要包括四种验证:文件格式验证、元数据验证、字节码验证和符号引用验证

3.2.2 准备

  • 为类变量分配内存,并为类变量分配零值
  • 特殊情况:final static 修饰的变量在这个阶段会被初始化为指定的初始值
  • 此阶段不会初始化实例变量

3.2.3 解析

  • 符号引用转换成直接引用的过程
  • 可能在 JVM 完成初始化后再执行
  • 符号引用
    以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可。
  • 直接引用
    (1)直接指向目标的指针(比如,指向“类型”【Class对象】、类变量、类方法的直接引用可能是指向方法区的指针)
    (2)相对偏移量(比如,指向实例变量、实例方法的直接引用都是偏移量)
    (3)一个能间接定位到目标的句柄

3.3 初始化阶段

类加载初始化的过程就是执行类构造器 clinit 方法的过程

3.3.1 clinit() 方法的产生

  1. 编译器收集静态变量赋值和静态代码块语句合并而成
  2. 方法中执行顺序由代码中定义顺序决定
  3. 静态块中可以赋值定义在其后的静态变量(赋值无效), 但不能访问(Illegal forward Reference)

3.3.2 clinit() 方法的执行

  1. 如果存在父类,先执行父类的 clinit ()
  2. 父接口中定义的变量被使用时, 父接口才会被初始化
  3. JVM 保证 clinit 方法在多线程执行过程中正确同步

3.3.3 初始化时机

  1. 新建类的对象
  2. 访问类的静态变量或赋值
  3. 调用类的静态方法
  4. 反射(如Class.forName(“xxx.xxx”))
  5. JVM 启动时标明为启动类的类
  6. 初始化一个类的子类
  7. JDK 7 开始提供的动态语言支持,java.lang.invoke.MethodHandle实例的解析结果 REF_getStatic 、REF_putStatic、REF_invokeStatic句柄对应的类没有初始化

四、类加载器

4.1 分类

在这里插入图片描述JVM 支持两种类加载器:启动类加载器和自定义类加载器

  • 启动类加载器
    JVM 的一部分, 采用 C++ 编写, 只有 Bootstarp ClassLoader
  • 自定义加载器
    独立存在于 JVM 之外, Java 语言编写,继承 java.lang.ClassLoader 类。

4.2 使用 ClassLoader

  • 类体系结构
    在这里插入图片描述
  • 获取 ClassLoader
    在这里插入图片描述

五、类加载机制

5.1 双亲委派机制

在这里插入图片描述

5.1.1 概念解释

  • 双亲
    除启动类加载器外,其他加载器都有父类加载器
    应用程序默认的类加载器是应用类加载器
  • 委派机制
    类加载器接收到加载请求后,会将加载请求委托给父类加载器加载
    父类加载器无法完成加载时,子类才尝试加载

5.1.2 双亲委派机制带来的好处

  • 使 java 类具备了一种带有优先级的层次关系
  • 避免类的重复加载

5.2 破坏双亲委派机制

双亲委派机制并非强制,只是一种约定俗成。

5.2.1 重写 loadClass() 方法

双亲委派机制是 JDK 1.2 中引入的, 为了兼容已有代码,无法采用技术手段避免 loadClass()方法被子类覆盖,而双亲委派机制主要是通过该方法实现的。

5.2.2 反向委托

在这里插入图片描述启动类加载器无法识别、加载 SPI 提供的类库, java 设计团队通过线程上下文类加载器来加载 SPI 的服务代码。线程上下文加载器默认为应用类加载器

5.2.3 程序动态性

由于用户对程序动态性的追求而导致的, 这里所说的“动态性”指的是一些非常“热”门的名词: 代码热替换(Hot Swap) 、 模块热部署(Hot Deployment) 等。
在OSGi环境下, 类加载器不再双亲委派模型推荐的树状结构, 而是进一步发展为更加复杂的网状结构

系列学习

画图学JVM (一)相关资料和学习计划 《硅谷2020最新版宋红康JVM》
画图学JVM (二)章节目录
画图学JVM (三)01 JVM 与 Java 体系结构
画图学JVM (四)02 类加载子系统
画图学JVM (五) 03 运行时数据区概述和线程
画图学JVM (六) 04 程序计数器

附件

《尚硅谷2020最新版宋红康JVM》01 JVM 与 Java 体系结构 学习记录 PPT
《尚硅谷2020最新版宋红康JVM》02 类加载子系统 学习记录 PPT
《尚硅谷2020最新版宋红康JVM》03 运行时数据区概述和线程 PPT
《尚硅谷2020最新版宋红康JVM》04 程序计数器 PPT
《尚硅谷2020最新版宋红康JVM》推荐的资料和工具集.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值