JVM

2020/10/21 20:10 下午 posted in  JVM

JVM 是 Java 虚拟机,运行在操作系统之上的,与硬件没有直接的交互。

类加载过程

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

Java中,类型的加载、连接和初始化过程都是在程序运行期间完成的。

class文件中的类从加载到JVM内存中,到卸载出内存的生命周期有7个,加载、验证、准备、解析、初始化、使用、卸载,

类加载机制在前5个阶段
16030972346717

加载

简单来说,加载指的是把class字节码文件从各个来源通过类加载器装载入内存中。

在加载阶段,虚拟机需要完成三件事

  1. 通过一个类的全限定名来获取定义此类的二进制字节流;
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

两个重点

  1. 字节码来源

通过一个类的全限定名来获取定义此类的二进制字节流,可以是通过jar包、war包、网络、JSP文件来获取

  1. 类加载器

一般包括启动类加载器、扩展类加载器、应用类加载器以及自定义类加载器。

验证

验证是连接阶段的第一步,

主要是为了保证加载进来的 Class 的字节流符合虚拟机规范,不会造成安全错误。

  1. 文件格式验证
  2. 元数据验证
  3. 字节码验证
  4. 符号引用验证

文件格式验证

第一阶段:验证字节流是否符合Class文件格式的规范,包含

  • 是否以魔数0xCAFEBABE开头
  • 主、次版本号是否在当前虚拟机处理范围之内,java8 版本是52
  • 常量池的常量中是否有不被支持的常量类型(检查常量tag标志)
  • 指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量
  • CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据
  • class文件中各个部分及文件本身是否有被删除的或附加的其他信息
  • 。。。

元数据验证

第二阶段,是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言规范的要求,这个阶段可能包含的验证点如下:

  • 这个类是否有父类
  • 这个类的父类是否继承了不允许被继承的类
  • 如果这个类不是抽象类,是否实现了其父类或接口之中要求实现的所有方法
  • 类中的字段、方法是否与父类产生矛盾
  • 。。。

字节码验证

第三阶段是整个验证阶段最复杂的一个阶段,主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。保证被校验类的方法在运行时不会做出危害虚拟机安全的事件

  1. 保证跳转指令不会跳转到方法体以外的字节码指令上
  2. 保证方法体中的类型转换是有效的

方法体的Code属性的属性表中增加了一项名为StackMapTable的属性

符号引用验证

最后一个阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接的第三阶段--解析阶段中发生。符号引用验证通常需要校验:

  1. 符号引用中通过字符串描述的全限定名是否能够找到对应的类
  2. 在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段
  3. 符号引用中的类、字段、方法的访问属性是否可以被当前类访问

准备

主要是为类变量(注意,不是实例变量)分配内存,并且赋予初值。

初值,不是代码中具体初始化的值,而是变量的类型对应的默认值。

解析

将常量池内的符号引用替换为直接引用的过程。

  1. 符号引用
  2. 直接引用

初始化

这个阶段主要是对类变量进行初始化,执行类构造器的过程。