V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tzh476
V2EX  ›  程序员

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

  •  3
     
  •   tzh476 · 2019-12-26 23:01:06 +08:00 · 2565 次点击
    这是一个创建于 1554 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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. 方法调用和返回

    引用和参考

    文档、书籍参考

    • java 虚拟机规范
    • 《自己动手写 Java 虚拟机》
    • java 虚拟机规范(java se7)中文版
    • java 虚拟机规范(java se8)中文版
    • 周志明的《深入理解 java 虚拟机》

    代码参考

    工具

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

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

    主要出于学习目的, 功能完备上目前应该还是楼主稍优.
    FrankHB
        7
    FrankHB  
       2019-12-27 12:48:23 +08:00
    一般意义上的 GC 是包含 allocator 的,看了下这里 GC 就只是 collect 算法的实现?
    tzh476
        8
    tzh476  
    OP
       2019-12-27 15:29:21 +08:00
    @guxingke 昨天就 star 你了。比我写得好特别多,向你学习
    tzh476
        9
    tzh476  
    OP
       2019-12-27 15:36:47 +08:00
    @FrankHB 这样子呀。我看 hotspot 的源码是有 allocator,Java 还不知道怎么实现或者体现,先学习学习,我改下 github 说明,v2 好像改不了。是只有算法的体现,分配对象判断有没有达到堆内存的最大值,达到就执行算法移除对象。
    FrankHB
        10
    FrankHB  
       2019-12-27 23:53:37 +08:00   ❤️ 1
    @tzh476 因为不像 C#这样有提供 unsafe 之类的,我也不太清楚纯 Java 怎么有意义地(类似实际的 JVM 实现的行为地)允许实现包含分配的自举 GC。理论上也许可以 NIO ByteBuffer 之类的对象分配好 pin 住或者干脆 JNI 直接搞 heap……不过这样多此一举大概还不如直接整个模块用 C++实现了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2783 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 73ms · UTC 11:52 · PVG 19:52 · LAX 04:52 · JFK 07:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.