一、JVM层级关系
- Jvm虚拟机:包含 类装载子系统,字节码执行引擎,运行时数据区;
- 运行时数据区:包含 线程独享区,线程共享区;
- 线程独享区:包含 栈(线程栈、本地方法栈),程序计数器;
- 线程共享区:包含 堆,方法区;
- 线程栈:包含 多个栈帧;
- 栈帧:包含 局部变量表,操作数栈,动态链接,方法出口;
二、JVM组件作用
- 虚拟机层:
- 类装载子系统(双亲委派机制)
- java文件 通过javac,编译成class文件;
- 再通过 类装载子系统,装载到 运行时数据区;
- 运行时数据区 处理完成后,交由 字节码执行引擎;
- 字节码执行引擎(有三种方式)
- 1、字节码解释器:执行一行,翻译(解释)一行;从而将字节码,翻译成机器码。
- 速度比较慢;
- 2、JIT(just in time 即时编译):一次性翻译成字节码。
- 速度快(第一次比较慢,后面不需要翻译,很快);
- 3、Mixed mode:混合执行方式。
- 1、字节码解释器:执行一行,翻译(解释)一行;从而将字节码,翻译成机器码。
- 运行时数据区
- 类装载子系统(双亲委派机制)
- 运行时数据区层:
- 本地方法栈: 线程独享;执行native修饰的C、C++等非java语言方法。
- java栈(线程栈):线程独享(每个线程会有自己的 栈帧);
- 程序计数器(PC Program Counter Register):线程独享;用来存储即将要执行指令的地址;
- PC会记录,每条即将执行的指令行号;
- 指令获取完后PC+1,指向下一指令;
- 取指令,寄存器会从PC中获取指令。
- 堆:多线程共享;实例对象(非静态成员变量,集合对象);
- 非静态成员变量,属于实例对象;
- 方法区(元空间):多线程共享;非堆(使用直接内存,即系统内存,而非JVM虚拟机的内存);
- class文件的相关信息(类被加载的时候,放入元空间)
- 类的字节码、及结构
- 运行时常量池;
- 静态成员变量、静态方法;
- class文件的相关信息(类被加载的时候,放入元空间)
- java栈(栈帧)层:
- 局部变量表:储存局部变量的地方;
- 操作数栈: 需要运算的数据临时存放;
- 动态连接:将’符号引用’替换成’直接引用’的过程;指向对象、集合的堆地址;
- java编译后,每个class文件都是独立的,类之间的引用采用’符号引用’(因为类还未加载到堆,不知道具体堆内存地址,采用符号代替。)
- 类似:sql预编译的占位符;解析(resolve)后,替换成真正的变量,组成完成的sql。
- 方法出口(返回地址、栈帧出栈):方法 返回指令、方法抛出异常 后,返回到主方法里;
- 记录返回的相关信息(主方法的程序计数器的值:也就是主方法运行到的位置,方便主方法恢复执行)。
- 方法返回指令;如return;
三、在栈中执行数学计算过程
// 代码
@Test
public void testClassCode(){
int a = 3;
int b = 4;
int c = 10;
int d = (a + b) * c;
}
// 字节码
0 iconst_3 将3压入操作数栈
1 istore_1 将3存入本地变量表
2 iconst_4 将4压入操作数栈
3 istore_2 将4存入本地变量表
4 bipush 10 将10压入操作数栈
6 istore_3 将10存入本地变量表
7 iload_1 将3从局部变量表中取出
8 iload_2 将4从局部变量表中取出
9 iadd 遇到运算符+(将3、4、运算符+,弹出栈运算;并将运算结果7再压栈
10 iload_3 将10从局部变量表中取出
11 imul 遇到运算符*(将10、7、运算符*,出栈运算;并将运算结果70再压栈
12 istore 4 将70存入本地变量表
14 return
注释
- 0 iconst_3 压栈
- 1 istore_1 int存储到本地变量中
- 4 bipush 10 压栈
- 压栈的字节指令:
- 小于等于-2:bipush -2;
- -1:iconst_m1;
- 0到5:iconst_1;
- 大于等于6:bipush 6;
- 压栈的字节指令:
- 7 iload_1 从局部变量加载int