Skip to content

Commit 3023bb4

Browse files
committed
完成02-虚拟机字节码执行引擎_00-虚拟机栈栈帧结构
1 parent dda5a25 commit 3023bb4

8 files changed

+118
-1
lines changed

Ch1-Java内存管理机制/03-Java内存分配策略.md

+8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22

33
![内存分配与回收策略.png](./pic/内存分配与回收策略.png)
44

5+
<!-- TOC -->
56

7+
- [Java 内存分配策略](#java-内存分配策略)
8+
- [优先在 Eden 区分配](#优先在-eden-区分配)
9+
- [大对象直接进入老年代](#大对象直接进入老年代)
10+
- [长期存活的对象将进入老年代](#长期存活的对象将进入老年代)
11+
- [空间分配担保](#空间分配担保)
12+
13+
<!-- /TOC -->
614

715
> **新生代和老年代的 GC 操作**
816
>

Ch2-Java虚拟机程序执行/02-虚拟机字节码执行引擎.md

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# 虚拟机栈栈帧结构
2+
3+
![虚拟机栈栈帧结构.png](./pic/虚拟机栈栈帧结构.png)
4+
5+
<!-- TOC -->
6+
7+
- [虚拟机栈栈帧结构](#虚拟机栈栈帧结构)
8+
- [局部变量表](#局部变量表)
9+
- [局部变量表的空间分配](#局部变量表的空间分配)
10+
- [Slot 的复用](#slot-的复用)
11+
- [操作数栈](#操作数栈)
12+
- [动态连接](#动态连接)
13+
- [方法返回地址](#方法返回地址)
14+
15+
<!-- /TOC -->
16+
17+
## 局部变量表
18+
19+
- 存放方法参数和方法内部定义的局部变量;
20+
- Java 程序编译为 class 文件时,就确定了每个方法需要分配的局部变量表的最大容量。
21+
- 最小单位:Slot;
22+
- 一个 Slot 中可以存放:boolean,byte,char,short,int,float,reference,returnAddress (少见);
23+
- 虚拟机可通过局部变量表中的 reference 做到:
24+
- 查找 Java 堆中的实例对象的起始地址;
25+
- 查找方法区中的 Class 对象。
26+
27+
### 局部变量表的空间分配
28+
29+
![局部变量表的空间分配.png](./pic/局部变量表的空间分配.png)
30+
31+
### Slot 的复用
32+
33+
**定义:** 如果当前位置已经超过某个变量的作用域时,例如出了定义这个变量的代码块,这个变量对应的 Slot 就可以给其他变量使用了。但同时也说明,只要其他变量没有使用这部分 Slot 区域,这个变量就还保存在那里,这会对 GC 操作产生影响。
34+
35+
**对 GC 操作的影响:**
36+
37+
```java
38+
public static void main(String[] args) {
39+
{
40+
byte[] placeholder = new byte[64 * 1024 * 1024];
41+
}
42+
System.gc();
43+
}
44+
```
45+
46+
`-verbose:gc` 输出:
47+
48+
```
49+
[GC (System.gc()) 68813K->66304K(123904K), 0.0034797 secs]
50+
[Full GC (System.gc()) 66304K->66204K(123904K), 0.0086225 secs] // 没有被回收
51+
```
52+
53+
进行如下修改:
54+
55+
```java
56+
public static void main(String[] args) {
57+
{
58+
byte[] placeholder = new byte[64 * 1024 * 1024];
59+
}
60+
int a = 1; // 新加一个赋值操作
61+
System.gc();
62+
}
63+
```
64+
65+
`-verbose:gc` 输出:
66+
67+
```
68+
[GC (System.gc()) 68813K->66320K(123904K), 0.0017394 secs]
69+
[Full GC (System.gc()) 66320K->668K(123904K), 0.0084337 secs] // 被回收了
70+
```
71+
72+
**第二次修改后,placeholder 能被回收的原因?**
73+
74+
- placeholder 能否被回收的关键:局部变量表中的 Slot 是否还存在关于 placeholder 的引用;
75+
- 出了 placeholder 所在的代码块后,还没有进行其他操作,所以 placeholder 所在的 Slot 还没有被其他变量复用,也就是说,局部变量表的 Slot 中依然存在着 placeholder 的引用;
76+
- 第二次修改后,int a 占用了原来 placeholder 所在的 Slot,所以可以被 GC 掉了。
77+
78+
79+
80+
## 操作数栈
81+
82+
- 元素可以是任意 Java 类型,32 位数据占 1 个栈容量,64 位数据占 2 个栈容量;
83+
- Java 虚拟机的解释执行称为:基于栈的执行引擎,其中 “栈” 指的就是操作数栈;
84+
85+
86+
87+
## 动态连接
88+
89+
- 指向运行时常量池中该栈帧所属方法的引用;
90+
- 为了支持方法调用过程中的动态连接,什么是动态连接会在下一篇文章进行讲解,先知道有这么个东西就行。
91+
92+
93+
94+
## 方法返回地址
95+
96+
- **两种退出方法的方式:**
97+
- 遇到 return;
98+
- 遇到异常。
99+
- **退出方法时可能执行的操作:**
100+
- 恢复上层方法的局部变量表和操作数栈;
101+
- 把返回值压入调用者栈帧的操作数栈;
102+
- 调整 PC 计数器指向方法调用后面的指令。
103+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# 方法调用
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# 基于栈的字节码解释执行引擎
2+
Loading
Loading

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717

1818
- [00-Class文件的组成结构](./Ch2-Java虚拟机程序执行/00-Class文件的组成结构.md)
1919
- [01-虚拟机的类加载机制](./Ch2-Java虚拟机程序执行/01-虚拟机的类加载机制.md)
20-
- [02-虚拟机字节码执行引擎](./Ch2-Java虚拟机程序执行/02-虚拟机字节码执行引擎.md)
20+
- 02-虚拟机字节码执行引擎
21+
- [00-虚拟机栈栈帧结构](./Ch2-Java虚拟机程序执行/02-虚拟机字节码执行引擎_00-虚拟机栈栈帧结构.md)
22+
- [01-方法调用](./Ch2-Java虚拟机程序执行/02-虚拟机字节码执行引擎_01-方法调用.md)
23+
- [02-基于栈的字节码解释执行引擎](./Ch2-Java虚拟机程序执行/02-虚拟机字节码执行引擎_02-基于栈的字节码解释执行引擎.md)
2124
- [附录0-实现Java类的热替换](./Ch2-Java虚拟机程序执行/附录0-实现Java类的热替换.md)
2225

2326
### 虚拟机性能监控及故障处理

0 commit comments

Comments
 (0)