JVM源码解析
一、java虚拟机概述
1. java程序的跨平台性
之前的话,通过Linux或者Windows开发,当需要跨平台时,程序不能运行。java出现后,产生了jvm,针对不同的操作系统,产生了不同的java虚拟机。
在Java虚拟机中执行的指令,称为Java字节码指令。
下面显示了同一个Java程序,被编译为一组Java字节码的集合之后,可以通过Java虚拟机运行于不同的操作系统上,它以Java虚拟机为中介,实现了跨平台的特性。
2. JVM的基本结构
类加载子系统:java文件先被编译成class文件,类加载子系统(classLoader)加载class文件,在jvm层面,就会涉及类加载里的加载、验证、准备、解析、初始化五个步骤,实现类的加载行为。当class文件被加载完,就会进入JMM。
JMM:java 内存模型,包括:公有的方法区、java堆、私有的java栈、本地方法栈、PC寄存器
两个线程同时请求一个路径,请求的资源可以互通认为是公有的,反之为私有的。
栈对应的是方法,java栈是自己本地写的方法,本地方法栈是native方法,私有则意味着两个线程互不打扰,A线程运行到一个位置,此时B线程进来了,私有则意味着B要从头运行。
class文件经过五个步骤加载完成后,类信息保存到方法区中,对象调用之后才会用到JMM另外四个位置。
垃圾回收系统:失去引用的对象为垃圾对象。包括:垃圾回收算法和垃圾回收器。
执行引擎:负责虚拟机的字节码。(忽略)
3. JVM类加载流程和内存结构总览
4. 类加载——加载阶段
通过类的全路径名称,读取类的二进制数据流。解析类的二进制数据流,转化为方法区(永久代or元空间)内部的数据结构。创建java.lang.Class类的实例对象,表示该类型。
5. 类加载——验 证 阶 段
它的目的是保证第一步中加载的字节码 是合法且符合规范的。 大体分为4步验证:
格式检查:检查魔数、版本、长度等等。
语义检查:抽象方法是否有实现类、 是否继承了final类等等编码语义上的 错误检查。
字节码验证:跳转指令是否指向正确的位置,操作数类型是否合理等。
符号引用验证:符号引用的直接引用是否存在。
6. 类加载——准 备 阶 段
准备阶段是正式为类变量分配内存并设置类 变量的初始值阶段,即:在方法区中分配这些变量所使用的内存空间。
注意这里所说的初始值概念,比如一个类变 量定义为:public static int v = 8080; 实际上变量v在准备阶段过后的初始值为0而不是 8080,将v赋值为8080的put static指令是程 序被编译后,存放于类构造器方法之中。
但是注意,如果声明为:public static final int v = 8080; 在编译阶段会为v生成 ConstantValue属性,在准备阶段虚拟机会根 据ConstantValue属性将v赋值为8080。
7. 类加载——解 析 阶 段
解析阶段是指虚拟机将运行时常量池中的符号引用替换为直接引用的过程。
符号引用就是class文件中的:CONSTANT_Class_info、CONSTANT_Field_info、 CONSTANT_Method_info 等类型的常量。
8. 类加载——初 始 化 阶 段
到达这个阶段,类就可以顺利加载到系统中。此时,类才会开始执行Java字节码。初始化阶段是执行类构造器方法的过程。
方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证子方法执行之前,父类的方法已经执行完毕,如果一 个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成() 方法。