JVM技术总结之三——类加载机制

8 篇文章 0 订阅
8 篇文章 0 订阅

接上篇《JVM技术总结之二——GC机制》

三. 类加载机制

参考地址:

《类加载机制-深入理解jvm》

《Java Class文件格式、常量池项目的类型、表的结构》

3.1 类的加载过程

Java 类的加载过程主要分为五步:加载验证准备解析初始化。其中验证、准备、解析可以合称为连接。此外,这五步的顺序并不是完全固定的,比如为了支持动态绑定,解析的过程可以放在初始化之后。类的加载过程如下图所示:
JVM类加载过程

3.1.1 加载

加载过程主要做三件事情:

  1. 根据全类名获取 *.class 文件的路径,通过二进制流读入 JVM 的方法区;
  2. 在方法区中将该字节流转为方法区的运行时数据结构;
  3. 在堆中生成代表该类的 java.lang.Class 对象,Class 对象的实例作为访问方法区中运行时数据结构的访问入口

3.1.2 校验

校验阶段主要确保 Class 文件字节流中的内容不会违反当前 JVM 的规范,不会危害到 JVM 运行时的安全。主要验证的有文件格式、元数据、字节码、符号引用

3.1.3 准备

准备阶段主要是将为类变量分配内存,并初始化为默认值。以下面的片段为例:

public static int value = 111;

需要注意的是,在准备阶段对于 int 类型,初始默认值为 0 而不是 111。同样的,其他基本类型的初始默认值都是该基本类型的默认值(如 double 的 0.0)。将 value 赋值为 111 的操作在初始化的步骤(即 clinit 方法)中进行。

3.1.4 解析

解析是将符号引用转换为直接引用的过程。

  • 符号引用:一组用于标识类型的符号,符合 Java 虚拟机规范的常量表,例如其中一项常量池项目类型如下图所示;
  • 直接引用:在内存中能够唯一标识对象的引用。可以是内存指针、偏移量、或者是能间接定位到目标的句柄等。
    常量池项目类型

3.1.5 初始化

执行类构建方法 clinit 的过程。clinit 方法由所有类变量的赋值动作静态语句块 static{} 合并而来,这其中也包含了父类的 clinit 方法(类变量赋值动作与父类的静态语句块),同时在执行一个类的 clinit 方法时,也会通过递归方式保证其父类的 clinit 方法先被调用

此外对于初始化阶段,只有几种情况才会要求类立刻执行 clinit 方法:

  1. new:new 关键字某个未被初始化的类;
  2. 父类:初始化某子类时,父类未被初始化,则先初始化父类;
  3. 反射:通过反射调用某个未初始化的类;
  4. main 方法所在类

3.2 类加载器

ClassLoader 中有一个 ClassLoader parent,记录其父类加载器。根类加载器 bootstrap ClassLoader 是最顶层的 ClassLoader,没有父类加载器。类加载器的加载范围不同,如果子类加载器想要加载父类加载器已经加载的类,可以通过双亲委派机制,直接访问父类加载器已经加载的类。
但是有的时候父类加载器也需要加载子类加载器的 Class,这时候就需要打破双亲委派机制,主要方式是使用 Thread 类里的线程上下文类加载器的方法 setContextClassLoader。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值