jvm类加载过程_JVM的类加载过程是怎么样的?

0cf8790782597ef2c7e70109a05495db.png

类加载过程分为加载、验证、准备、解析、初始化五个阶段。其中验证、准备、解析又合称为连接阶段。

加载

加载阶段是将class文件读取到内存的过程。具体分为三步,第一步根据class的全限定名获取class的二进制字节流,第二步将class的二进制字节流转化成数据结构存储在方法区,第三步在虚拟机堆中生成一个java.lang.class对象用来指向方法区中的class数据结构。

验证

验证阶段是验证class文件可执行性方面的步骤,具体分为四个部分。文件格式验证、元数据验证、字节码验证、符号引用验证。

  • 文件格式验证,其作用是保证字节流符合class文件格式规范,比如检查是否是以魔数CAFEBABE开头的、主次版本号是否合法、常量池是否有不被支持的常量类型等等。这个阶段是以二进制字节流进行校验的,只有完成了这个阶段的校验才会将二进制字节流按照数据结构存储到方法区中。
  • 元数据验证,对字节码描述的信息进行语义分析,以保证其描述的信息符合《java语言规范》,比如这个类是否有父类(除了java.lang.Object之外,所有类都应当有父类)、这个类是否继承了不允许被继承的类(被final修饰的类)、如果这个类不是抽象的是否实现其父类或者接口要求实现的方法。
  • 字节码验证,通过对数据流分析和控制流分析,验证程序语义是否是合法的、符合逻辑的。比如保证操作数栈上的数据类型和指令代码序列配合工作(比如操作数栈上放了一个int类型的数据,使用时却按long类型来载入本地变量表)、保证跳转操作不要跳转到方法体以外、保证类型转换是有效的。
  • 符号引用验证,是对类的各项信息进行匹配性校验,查看他所依赖的外部类、方法、字段等资源是否有缺少或者被禁止访问的情况。比如符号引用中通过全限定名是否可以找到对应的类、指定的类当中是否存在符合的方法和字段、符号引用中的类、字段、方法的可访问性是否可以被当前类访问。这个动作发生在符合引用转化为直接引用的解析阶段。

准备

为类中的定义的静态变量设置初始值(零值,不是最终值)的阶段。如果变量是一个常量,那么会直接初始化为最终值。

解析

将符号引用转化为直接引用的过程。

初始化

虚拟机会自动对类中的变量赋值动作和静态代码块会生成一个<clinit>方法,并在初始化阶段执行这个方法。

  • java虚拟机会保证父类的<clinit>方法早于子类的<clinit>方法被调用。
  • 接口虽然不会有静态代码块,但是会有变量赋值所以也会有clinit方法,但是父接口的<clinit>仅当父类变量被调用才会初始化<clinit>。
  • 如果没有变量赋值和静态代码块则不会有<clinit>方法。
  • java虚拟机本身会保证<clinit>调用的线程安全。

通过以上五个步骤就可以完成整个类的加载过程,内容总结来自《深入理解Java虚拟机》,欢迎讨论共同学习。

以下是关于类加载过程的几个扩展问题。

扩展问题

静态代码块可以使用定义在它之后的变量吗?

不可以。静态代码块可以给定义在它之后的变量进行赋值,但是不能使用。决定这一现象的动作在类初始化阶段。

什么是符号引用,什么是直接引用?

符号引用是使用文本字符串格式来表示引用关系的形式。这个字符串包含足够的信息,当你需要用的时候可以通过字符串搜索找到相应位置。
直接引用是虚拟机内存中的指针、偏移量或者其他形式的能够被jvm直接使用的信息。

饿汉式单例为什么能保证线程安全?

在类的初始化阶段会对每个类生成<clinit>方法,这个过程会初始化变量。并且java虚拟机规范强制约束<clinit>方法需要保证线程安全。

Photo on <a href="Foter">Foter.com</a>

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值