最近抽空重新温习一下JVM的概念,现在把心得记录一下。
第一部分:根据学习抽象出一个JVM的概念图,描述各个主要组件的构成和基本作用。
第二部分:根据结构图,对内容进行说明。
1)--JVM的概念
JVM是JAVA VIRTUAL MACHINE的缩写,它是一个虚拟的计算机设备。
一般的高级语言要想在不同的平台上运行,那么首先要编译成平台识别的编译语言。
java具有跨平台性,其中的核心特点就是使用了JVM。
使用了JVM之后,java只需要编译成JVM中识别的字节码就可以了,然后JVM会根据运行平台,把字节码转换为平台识别的计算机指令。
一次编译,到处执行。
2)数据类型
2.1基本数据类型,数据类型及字节数。
1-----------2-----------4-----------8
byte short int long
char float double
上述7种数据类型不需要硬件标记,操作这些数据时字节码本身已经给出了操作类型,例如:fadd,iadd,dadd
2.2其他类型
4字节:object类型,盛放对其他JavaObject的引用。
注意:数组类型会被当做Object类型处理。所有的数据都应该遵守数据类型规则。否则jvm会拒绝执行字节码。
3)组件
为了实现跨平台的特性,JVM设计出组件标准,支撑虚拟的计算机模型。
1.JVM指令系统
2.JVM寄存器
3.JVM栈结构
4.JVM碎片回收堆
5.JVM存储区-常量池
6.JVM存储区-方法区
4)原理
JVM是Java的基础和核心,是JAVA编译器同操作系统及硬件平台之间的中间层,是一个抽象的计算机。
java编译器生成JVM识别的字节码,JVM根据字节码生成操作系统的机器码,在对应的平台上执行。
对于JAVA的程序来说,JVM是一个程序运行容器,对于操作系统而言JVM是一个进程。
4.1)执行过程--JVM初始化作业
程序执行时,首先调用JAVA.exe(java.exe是一个外壳,其实内部发生核心作用的时JVM.dll)
java_md.c,java.c两个文件调用jvm.cfg,进行虚拟机的初始化,并且装载jvm.dll。
jvm.dll挂载JNIEVE(java环境),接下来就开始加载类,进行操作。
4.2)执行过程--类加载
classLoader加载要执行的.class文件
进行字节码的校验
申请并管理存储区域,垃圾回收
使用java解释器进行解释,生成机器码
操作系统执行机器码
5)指令系统
指令系统是指令的集合,每条指令由操作码和操作数组成。
操作码由8位2进制数组成,最大256种,现在已经使用160种以上。
操作数根据实际变化而变化,超过8位时,新增一个字节。
如 iadd,iand等都是操作码。
6)寄存器
分为四种
pc 程序计数器指针
optop 操作数栈顶指针
vars 局部变量第一变量指针
frame 当前执行环境指针
*所有的寄存器都是32位
7)栈结构
类加载后会为每个方法生成一个栈结构。
包含如下几种区域:
局部变量:存储局部变量。以32位为单位存储,long和double占用两个局部变量。vars寄存器通过偏移进行局部变量的访问。
操作数栈:以32为基础单位。运算过程中存储操作数以及操作结果;调用方法时传递参数,并放置调用结果。机器指令取信息时,只从操作数栈取数据。
执行环境:存放解释器所需要的各种信息,如局部变量指针,栈顶和栈底指针,上一次执行的方法。
动态链接:以符号指针的形式访问方法和变量,并且把变量翻译成存储结构和偏移地址。
正常返回:正常返回时,调用方会得到一个返回结果。进一步的设置调用方的寄存器,如把PC加一个适当的数,能够进行下一个指令的访问。
异常捕捉:程序遇到类似于无法找到class(动态链接错),或者遇到空指针(运行时错误),接下来catch子句的匹配。
匹配原则:字节码发生异常的地点是catch的范围内,异常类型是catch的类型。
匹配顺序:从第一个异常catch子句到最后一个子句,逐层查找。找到后处理catch异常块代码。最终匹配失败,会执行最底层缺省块异常。
执行iadd时,需要调用寄存器frame,通过frame找到操作数栈,弹出两个操作数。
然后把计算结果,通过寄存器frame找到操作数栈,压倒栈顶。
8)回收堆
java类实例的空间由解释器进行分配和管理的。解释器记录对象的内存空间使用情况,当内存不再被使用时,由解释器负责把内存空间回收到堆中。
右侧为自我理解:可以理解Edan区域,survival区域,old区域。按步骤使用。
new时现在edan区域申请内存,不足时回收edan中不用对象。
内存还是不足时,把部分活性不足的对象放置到survival中。
survival区域不足时,把部分活性不足的对象放置到old中。
old区域不足时,gc整个old区域。
gc后还是不足时,报异常。
9)存储区域-常量池
存储: 类名,方法名,字段名称,常量。
10)存储池-方法区
存储:方法执行的字节码。
11)Java解释器
拿着JAVA和C++对比,可以理解如下:
Java源码和C++源码同样为高级语言;
Java编译后文件为二进制字节码,C++编译后文件为二进制机器码;
Java字节码在JVM的java解释其中执行,C++机器码在CPU中执行;
Java解释器是通过软件实现的虚拟cpu,其最终还会把字节码翻译成机器码在实际的CPU上执行;
只要运行平台上实现了java解释器,那么java就可以在这个平台上执行,目前部分平台不支持java,因为其没有实现java解释器;
12)运行数据
JVM启动和退出时会创建和销毁部分数据区域,线程创建和死亡时也会创建和销毁部分数据。
包含:寄存器,栈,堆,常量池,方法区。
13)其他
13.1)当开启新的线程时,会为线程创建java栈用以存放方法的调用状态。注意,本地方法的调用状态存放在栈结构的本地方法栈里。
同时会为线程设置PC 应用程序计数器寄存器,用以放置即将执行的命令。
13.2)JVM包括子系统(加载类子系统,指令运行引擎-解释器),指令集,数据类型,五大存储类型(寄存器,栈,堆,方法区,常量池)等。
13.3)JRE是java平台,JavaRuntimeEnvironment,所有java程序的运行基础。JDK安装时,必须有一个JRE支持它,安装了JDK后,会有一个JRE的目录。
JVM是JRE的核心部分,它是虚拟的计算机。有自己的一套组件,如CPU(指令运行引擎-JAVA解释器),寄存器,各种存储器,指令集等。
参看link:
https://baike.baidu.com/item/JVM/2902369