JVM基础 -- JVM字节码执行过程
本文将通过是实例简单介绍
JVM字节码
基于栈
的执行过程
Stack Frame
- 一个方法
从调用到执行完成
,对应着一个栈帧(Stack Frame
)在虚拟机栈(VM Stack
)里面从入栈到出栈
的过程 - 在
编译
成字节码
期间,栈帧需要多大的局部变量表(Local Variable Table
),多深的操作数栈(Operand Stack
)都已经完全确定,并且写入到方法表的Code
属性中 - 在
活动线程
中,只有位于栈顶的栈帧
才是有效的,称为当前栈帧
,与这个栈帧关联的方法称为当前方法
- 局部变量表
- 用于存放
方法参数
和方法内部定义的局部变量
- 方法表中的
locals
属性记录了局部变量表的最大容量
- 局部变量表的存储单元为
32-bit的slot
,boolean
、byte
、char
、short
、int
、float
等会占用一个slot
,long
和double
会占用两个slot
- 如果执行的是
实例方法
,那么第0个slot
默认存储this
- 为了
节省栈帧空间
,slot是可重用
的
- 用于存放
- 操作数栈
- 方法表中的
stack
属性记录了操作数栈的最大深度
- 操作数栈可以容纳任意的
Java
数据类型,32-bit
数据类型所占用的栈容量为1
,64-bit
数据类型所以占用的栈容量为2
- 方法表中的
代码
1 | package me.zhongmingmao.test; |
字节码
1 | # javap -v |
stack=2
,这个在分析下面16个JVM字节码指令
的运行过程后就能验证这是正确的,从Java源代码
是无法直观的得出这个值locals=4
,从Java源代码
可以看出,calc()
只定义了a
、b
、c
三个局部变量,而calc()
又是实例方法
,局部变量表第1个slot
默认会有记录this
,因此能得出locals=4
(在这里slot没有进行复用)- 在
JVM字节码
中的LocalVariableTable
属性,很清晰表述了局部变量表
的布局,其中需要注意的是Start
指的是局部变量生命周期开始的字节码偏移量
,Length
指的是作用范围覆盖的长度
,而并非变量本身的长度 args_size=1
,实例方法
默认会传入this
,因此args_size=1
执行过程
bipush 100
istore_1
iload_1
iload_2
iadd
iload_3
imul
ireturn
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.