JVM 和操作系统的关系
JVM 会将我们的字节码文件生成操作系统可以识别的机器码。

JVM 运行过程

JIT
解释执行
运行时数据区
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域。

线程私有的包含:虚拟机栈、本地方法栈、程序计数器
线程共享的:方法区、堆
程序计数器
指向当前线程正在执行的字节码指令的地址。
我们可以利用 javap -c
对一个类进行反汇编。在得到的字节码中 我们可以看到类型下图一样的内容

其中 code
代表的就是针对方法的偏移量。大体可以理解为程序计数器,记录的字节码的地址。
程序计数器的作用就是在 由于CPU 进行时间片轮转而导致线程切换的时候记录当前的信息。
程序计数器是 JVM 内存区域中,唯一不会 OOM (OutOfMemory) 的,因为占用内存小。
虚拟机栈
栈:先进后出
存储当前线程运行方法所需的数据、指令、返回地址
在 hotspot 版本默认大小为 1M
栈帧
一个方法对应一个栈帧
栈帧内部包括:
- 局部变量表
- 操作数栈
- 动态连结
- 完成出口
局部变量表
用来存储局部变量,只能存储基础类型和引用。
操作数栈
存储方法的执行
栈帧执行对内存区域的影响
通过下面方法来解析栈帧的执行

下面是 work 方法生成的字节码

分析
首先程序执行 main 方法将 main 方法入栈

然后在 main 方法中调用 work 方法,将 work 方法入栈

然后进行 work 方法中的操作,这个操作是在操作数栈进行的,
首先将 int 型的 1 入操作数栈

然后将操作数栈栈顶 int 型的数值,存入局部变量表中下标为 1 的位置,字节码中的 istore_1
中 1 标识下标
局部变量表中的 this
表示类的实例本身,在非静态的方法中,需要通过 this
来访问外部。

上面两步骤将 int x = 1
执行完成,同理执行 int y = 2
;

接下来回执行 (x+y) * 10
, 首先会将局部变量表中的值加入操作数栈

然后进行相加,相加分为三步
- 先将栈顶出栈
- 相加
- 将结果压入操作数栈


然后将 10 的值扩展成int, 并压入操作数栈

然后进行相乘,同样进行三步
- 出栈
- 相乘
- 入栈


因为结果是存到一个变量的,所以需要将栈顶的内容存入局部变量表下标为 3 的位置

然后将需要返回的值加载到操作数栈

Java 中进行解析执行是基于栈的,这个栈指的就是操作数栈,
C 语言是基于寄存器(硬件)的。
寄存器依赖于影响,效率快,但是移植性较差。
Java 不需要依赖硬件,兼容性好,效率较低。
动态连结
多态:动态分派、静态分派
动态确定去执行哪个方法
完成出口 (返回地址)
<深入理解 Java 虚拟机 > p300
虚拟机参数配置
- Xss
设置线程堆栈的大小
网友评论