前置知识
- JVM运行时数据区
- 栈帧的组成
虚拟机栈 与 栈帧
虚拟机栈(JVM Stack
),由 栈帧 Frame
组成。
Frame
- 每个方法对应一个栈帧, 包括以下部分:
Local Variable Table
(局部变量表)Operand Stack
(操作数栈) 操作数栈(Operand Stack
)也常称为操作栈,它是一个后入先出(Last In FirstOut,LIFO)栈。 同局部变量表一样,操作数栈的最大深度也在编译的时候写入到Code属性的max_stacks数据项中。Dynamic Linking
(动态链接) 动态链接是一个将符号引用解析为直接引用的过程。return address
(返回地址) a() -> b(),方法a调用了方法b, b方法的返回值放在什么地方 方法退出时会做的操作:- 恢复上一个方法(调用者的栈帧)的
Local Variable Table
(局部变量表)和Operand Stack
(操作数栈) - 将返回的变量压入 上一个方法(调用者的栈帧)的
Operand Stack
(操作数栈) - 调整
Program Counter Register
(PC, 程序计数器) 的值为 当前帧的返回地址 - 当前栈帧弹出
JVM Stack
栈, - 执行
Program Counter Register
(PC, 程序计数器)指向的指令
- 恢复上一个方法(调用者的栈帧)的
理解JVM栈帧
用两个代码来帮助理解。
public static void main(String[] args) {
int i = 8;
i = i++;
System.out.println(i);
}
public static void main(String[] args) {
int i = 8;
i = ++i;
System.out.println(i);
}
这里两个代码分别打印什么呢?
结果是 9 和 8 。 为什么呢??
我们使用字节码原语来解析一下。
这里用到我们的一个IDEA 插件: jclasslib Bytecode viewer
i= i++
- 0 bipush
- 2 istore_1 ---> int i = 8;
- 3 iload_1
- 4 iinc 1 by 1 --> 完成 i++
- 7 istore_1 --> i = i++;
i = ++i
前面都是一样。 区别只在于 这个是先 iinc 1 by 1 后 iload_1
- 6 iload_1 --> 完成 ++i
- 7 istore_1 --> i = ++i;
来源:oschina
链接:https://my.oschina.net/langxSpirit/blog/3224968