Java 实现可 GC 的 JVM(每个模块有运行样例)

2019-12-26 23:01:06 +08:00
 tzh476

Java 实现简易 JVM
github 地址

主要模块和样例(github 有每个模块样例):

  1. 读取并解析 class 文件,如 String、Thread 等类(支持 jdk8 及以下)
  2. 取 opcode,解释执行程序。循环运算,入栈出栈
  3. 方法调用(静态方法、构造方法、实例方法(支持继承多态))
  4. 数组
  5. 字符串和字符串数组
  6. 调用本地方法
  7. gc(标记清除算法)

目录结构

com\zvm
    basestruct\                 #读取字节码为内存中 ClassFile 时的基本数据结构
    classfile\                  #类解析相关
       attribute\               #属性表:jdk8 中的 23 种属性
       constantpool\            #常量池:jdk8 中 10 种常量类型
       ClassFile.java           #解析后的 class 文件
       cp_info.java             #ClassFile 中的常量池表示
       field_info.java          #ClassFile 中的字段表示
       IOUtils.java             #解析字节码的工具类
       method_info.java         #ClassFile 中的方法表示
       ZvmClassLoader.java      #待重构
    draft\
    gc\
       GC.java                  #GC 类,目前只有标记清除算法
    interpreter\                
       CallSite.java            #调用方法时的入口
       CodeUtils.java           #控制 pc 的工具类
       Descriptor.java          #方法调用时,表示返回数据和入参结构
       Interpreter.java         #取 opcode 并执行的类
       Opcode.java              #指令
       Ref.java                 #表示 methodRef 或 fieldRef:含类名、描述符、方法名 /字段名
    jnative\java\lang\           #预留实现本地方法
    memory\
       ArrayFields.java         #保存堆中的数组
       JavaHeap.java            #表示堆,对象和数组都分配在这
       MethodArea.java          #方法区
       ObjectFields.java        #表示堆中的对象
    runtime\                    #运行时数据
       struct\                  #一些基本数据结构
       JavaClass.java           #运行时表示:ClassFile 的入口,加一些类的信息
       JavaFrame.java           #运行时表示:一个方法所用的帧
       JThread.java             #运行时表示:一个线程(目前未实现多线程)
       LocalVars.java           #运行时表示:帧中的局部变量表
       OperandStack.java        #运行时表示:帧中的操作数栈
       RunTimeEnv.java          #运行时的环境,包括 JavaHeap、MethodMrea 等
       StaticVars.java          #JavaClass 中的静态字段分配内存
       ThreadStack.java         #线程栈:运行时,方法调用帧由底至上组成线程栈
    utils\
       TypeUtils.java           #类型转换工具类
       Vars.java                #供 LocalVars、LocalVars、ObjectFields 继承使用
    Cmd.java                    #解析命令行
    JavaMain.java               #启动入口类,含 main 方法
    ZVM.java                    #表示虚拟机

已实现指令(绝大部分实现了)

  1. 加载(load)、存储(store)指令,将数据在局部变量表和操作数栈中来回传输
  2. 运算指令
  3. 类型转换指令
  4. 对象创建和操作
  5. 操作数栈管理
  6. 控制转移
  7. 方法调用和返回

引用和参考

文档、书籍参考

代码参考

工具

2580 次点击
所在节点    程序员
10 条回复
blindpirate
2019-12-26 23:15:12 +08:00
虽然实践中没什么意义,但是对于学习还是非常有帮助的,对楼主表示钦佩。
tzh476
2019-12-26 23:21:26 +08:00
@blindpirate 谢谢~,主要是加深对 JVM 的理解。
fpure
2019-12-27 00:04:24 +08:00
有人用 go 实现过 jvm,楼主不如用 rust 试试,更有实际价值
tzh476
2019-12-27 00:40:28 +08:00
@fpure 好建议。看下后面有没有机会,现在我对 java 并发本质这些还没理解,正想读写 diy os 的书模仿写一个 diy os 来理解。我写的这个参考了用 go 实现的大神,还有个用 c++实现的大神,引用中有写。
solupro
2019-12-27 09:52:45 +08:00
已 star,学习
guxingke
2019-12-27 10:58:29 +08:00
已 star , 互相学习了, 跟我实现的应该是同期开工的. 2 个月前 .

https://github.com/guxingke/mini-jvm

主要出于学习目的, 功能完备上目前应该还是楼主稍优.
FrankHB
2019-12-27 12:48:23 +08:00
一般意义上的 GC 是包含 allocator 的,看了下这里 GC 就只是 collect 算法的实现?
tzh476
2019-12-27 15:29:21 +08:00
@guxingke 昨天就 star 你了。比我写得好特别多,向你学习
tzh476
2019-12-27 15:36:47 +08:00
@FrankHB 这样子呀。我看 hotspot 的源码是有 allocator,Java 还不知道怎么实现或者体现,先学习学习,我改下 github 说明,v2 好像改不了。是只有算法的体现,分配对象判断有没有达到堆内存的最大值,达到就执行算法移除对象。
FrankHB
2019-12-27 23:53:37 +08:00
@tzh476 因为不像 C#这样有提供 unsafe 之类的,我也不太清楚纯 Java 怎么有意义地(类似实际的 JVM 实现的行为地)允许实现包含分配的自举 GC。理论上也许可以 NIO ByteBuffer 之类的对象分配好 pin 住或者干脆 JNI 直接搞 heap……不过这样多此一举大概还不如直接整个模块用 C++实现了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/632708

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX