# 用Java实现JVM第四章《运行时数据区》
作者:小傅哥
博客:https://bugstack.cn (opens new window)
沉淀、分享、成长,让自己和他人都能有所收获!😄
# 案例介绍
本案例初步实现运行时数据区里;线程、Java虚拟机栈、帧、操作数栈、局部变量表。
在运行Java程序时,Java虚拟机需要使用内存来存放各种各样的数据。Java虚拟机规范把这些内存区域叫作运行时数据区。运行时数据区可以分为两类:一类是多线程共享的,另一类则是线程私有的。多线程共享的运行时数据区需要在Java虚拟机启动时创建好在Java虚拟机推出时销毁。线程私有的运行时数据区则在创建线程时才创建,线程退出时销毁。
线程私有的运行时数据区用于辅助执行Java字节码。每个线程都有自己的pc寄存器(Program Counter)和Java虚拟机栈(JVM Stack)。Java虚拟机栈又由栈帧(Stack Frame,后面简称帧)构成,帧中保存方法执行的状态,包括局部变量表(Local Variable)和操作数栈(Operand Stack)等。在任一时刻,某一线程肯定是在执行某个方法。这个方法叫作该线程的当前方法;执行该方法的帧叫作线程的当前帧;声明该方法的类叫作当前类。如果当前方法是Java方法,则pc寄存器中存放当前正在执行的Java虚拟机指令的地址,否则,当前方法是本地方法,pc寄存器中的值没有明确定义。
Run-Time Data Area
├── Thread
│ └── pc
│ └── Jvm Stack
│ └── Frame
│ ├── Local Variable
│ └── Operand Stack
└── Heap
├── Method Area
│ └── Class
│ ├── Run-Time
│ └── Constant Pool
└── Object
2
3
4
5
6
7
8
9
10
11
12
13
# 环境准备
- jdk 1.8.0
- IntelliJ IDEA Community Edition 2018.3.1 x64
# 配置信息
- 调试配置
- 配置位置:Run/Debug Configurations -> program arguments
- 配置内容:-Xjre "C:\Program Files\Java\jdk1.8.0_161\jre" E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-04\target\test-classes\org\itstack\demo\test\HelloWorld
# 代码示例
itstack-demo-jvm-04
├── pom.xml
└── src
└── main
│ └── java
│ └── org.itstack.demo.jvm
│ ├── classfile
│ │ ├── attributes {BootstrapMethods/Code/ConstantValue...}
│ │ ├── constantpool {CONSTANT_TAG_CLASS/CONSTANT_TAG_FIELDREF/CONSTANT_TAG_METHODREF...}
│ │ ├── ClassFile.java
│ │ ├── ClassReader.java
│ │ └── MemberInfo.java
│ ├── classpath
│ │ ├── impl
│ │ │ ├── CompositeEntry.java
│ │ │ ├── DirEntry.java
│ │ │ ├── WildcardEntry.java
│ │ │ └── ZipEntry.java
│ │ ├── Classpath.java
│ │ └── Entry.java
│ ├── rtda
│ │ ├── Frame.java
│ │ ├── JvmStack.java
│ │ ├── LocalVars.java
│ │ ├── OperandStack.java
│ │ ├── Slot.java
│ │ └── Thread.java
│ ├── Cmd.java
│ └── Main.java
└── test
└── java
└── org.itstack.demo.test
└── HelloWorld.java
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Frame.java
package org.itstack.demo.jvm.rtda;
/**
* http://www.itstack.org
* create by fuzhengwei on 2019/4/26
* 栈帧
*/
public class Frame {
//stack is implemented as linked list
Frame lower;
//局部变量表
private LocalVars localVars;
//操作数栈
private OperandStack operandStack;
public Frame(int maxLocals, int maxStack) {
this.localVars = new LocalVars(maxLocals);
this.operandStack = new OperandStack(maxStack);
}
public LocalVars localVars(){
return localVars;
}
public OperandStack operandStack(){
return operandStack;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
JvmStack.java
package org.itstack.demo.jvm.rtda;
/**
* http://www.itstack.org
* create by fuzhengwei on 2019/4/26
* 虚拟机栈
*/
public class JvmStack {
private int maxSize;
private int size;
private Frame _top;
public JvmStack(int maxSize) {
this.maxSize = maxSize;
}
public void push(Frame frame) {
if (this.size > this.maxSize) {
throw new StackOverflowError();
}
if (this._top != null) {
frame.lower = this._top;
}
this._top = frame;
this.size++;
}
public Frame pop() {
if (this._top == null) {
throw new RuntimeException("jvm stack is empty!");
}
Frame top = this._top;
this._top = top.lower;
top.lower = null;
this.size--;
return top;
}
public Frame top(){
if (this._top == null){
throw new RuntimeException("jvm stack is empty!");
}
return this._top;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
LocalVars.java
package org.itstack.demo.jvm.rtda;
/**
* http://www.itstack.org
* create by fuzhengwei on 2019/4/26
* 局部变量表
*/
public class LocalVars {
private Slot[] slots;
public LocalVars(int maxLocals) {
if (maxLocals > 0) {
slots = new Slot[maxLocals];
for (int i = 0; i < maxLocals; i++) {
slots[i] = new Slot();
}
}
}
public void setInt(int idx, int val) {
this.slots[idx].num = val;
}
public int getInt(int idx) {
return slots[idx].num;
}
public void setFloat(int idx, float val) {
this.slots[idx].num = (Float.valueOf(val)).intValue();
}
public Float getFloat(int idx) {
int num = this.slots[idx].num;
return (float) num;
}
public void setLong(int idx, long val) {
this.slots[idx].num = (int) val;
this.slots[idx + 1].num = (int) (val >> 32);
}
public Long getLong(int idx) {
int low = this.slots[idx].num;
int high = this.slots[idx + 1].num;
return ((long) high << 32) | (long) low;
}
public void setDouble(int idx, double val) {
setLong(idx, (long) val);
}
public Double getDouble(int idx) {
return Double.valueOf(getLong(idx));
}
public void setRef(int idx, Object ref) {
slots[idx].ref = ref;
}
public Object getRef(int idx) {
return slots[idx].ref;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
OperandStack.java
package org.itstack.demo.jvm.rtda;
/**
* http://www.itstack.org
* create by fuzhengwei on 2019/4/26
* 操作数栈
*/
public class OperandStack {
private int size = 0;
private Slot[] slots;
public OperandStack(int maxStack) {
if (maxStack > 0) {
slots = new Slot[maxStack];
for (int i = 0; i < maxStack; i++) {
slots[i] = new Slot();
}
}
}
public void pushInt(int val) {
slots[size].num = val;
size++;
}
public int popInt(){
size --;
return slots[size].num;
}
public void pushRef(Object ref){
slots[size].ref = ref;
size++;
}
public Object popRef(){
size --;
Object ref = slots[size].ref;
slots[size].ref = null;
return ref;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Slot.java
package org.itstack.demo.jvm.rtda;
/**
* http://www.itstack.org
* create by fuzhengwei on 2019/4/26
* 数据槽
*/
public class Slot {
int num;
Object ref;
}
2
3
4
5
6
7
8
9
10
11
12
13
Thread.java
package org.itstack.demo.jvm.rtda;
/**
* http://www.itstack.org
* create by fuzhengwei on 2019/4/26
* 线程
*/
public class Thread {
//Program Counter 寄存器
private int pc;
//虚拟机栈
private JvmStack stack;
public Thread(){
this.stack = new JvmStack(1024);
}
public int pc(){
return this.pc;
}
public void setPC(int pc){
this.pc = pc;
}
public void pushFrame(Frame frame){
this.stack.push(frame);
}
public Frame popFrame(){
return this.stack.pop();
}
public Frame currentFrame(){
return this.stack.top();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 测试结果
100
-100
null
-100
2
3
4
微信搜索「bugstack虫洞栈」公众号,关注后回复「用Java实现jvm源码」获取本文源码&更多原创专题案例!