- Notifications
You must be signed in to change notification settings - Fork 4.1k
2019 05 05 用Java实现JVM第四章《运行时数据区》
作者:小傅哥
博客:https://bugstack.cn - 原创系列专题
沉淀、分享、成长,让自己和他人都能有所收获!
本案例初步实现运行时数据区里;线程、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
- 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
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; } }
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; } }
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; } }
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; } }
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; }
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(); } }
100 -100 null -100
上一篇:用Java实现JVM第三章《解析class文件》附[classReader拆解]
微信搜索「bugstack虫洞栈」公众号,关注后回复「用Java实现jvm源码」获取本文源码&更多原创专题案例!
小傅哥(微信:fustack),公众号:bugstack虫洞栈
| bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
🌏 知识星球:码农会锁

实战项目:「DDD+RPC分布式抽奖系统
」、专属小册、问题解答、简历指导、架构图稿、视频课程
🐲 头条
- 💥
🎁 Lottery 抽奖系统
- 基于领域驱动设计的四层架构的互联网分布式开发实践 -
小傅哥的《重学 Java 设计模式》
- 全书彩印、重绘类图、添加内容 -
⭐小傅哥的《Java 面经手册》
- 全书5章29节,417页11.5万字,完稿&发版 -
小傅哥的《手撸 Spring》
- 通过带着读者手写简化版 Spring 框架,了解 Spring 核心原理 -
🌈小傅哥的《SpringBoot 中间件设计和开发》
- 小册16个中间件开发30个代码库
⛳ 目录
💋 精选
🐾 友链
建立本开源项目的初衷是基于个人学习与工作中对 Java 相关技术栈的总结记录,在这里也希望能帮助一些在学习 Java 过程中遇到问题的小伙伴,如果您需要转载本仓库的一些文章到自己的博客,请按照以下格式注明出处,谢谢合作。
作者:小傅哥 链接:https://bugstack.cn 来源:bugstack虫洞栈
2021年10月24日,小傅哥
的文章全部开源到代码库 CodeGuide
中,与同好同行,一起进步,共同维护。
这里我提供 3 种方式:
- 提出
Issue
:在 Issue 中指出你觉得需要改进/完善的地方(能够独立解决的话,可以在提出 Issue 后再提交PR
)。 - 处理
Issue
: 帮忙处理一些待处理的Issue
。 - 提交
PR
: 对于错别字/笔误这类问题可以直接提交PR
,无需提交Issue
确认。
详细参考:CodeGuide 贡献指南 - 非常感谢你的支持,这里会留下你的足迹
- 加群交流 本群的宗旨是给大家提供一个良好的技术学习交流平台,所以杜绝一切广告!由于微信群人满 100 之后无法加入,请扫描下方二维码先添加作者 “小傅哥” 微信(fustack),备注:加群。

- 公众号(bugstack虫洞栈) - 沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。

感谢以下人员对本仓库做出的贡献或者对小傅哥的赞赏,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与我联系。