用 Java 实现一个简单的虚拟机 ?

Learning By Doing.java

最近开了个新坑, 目的是用 Java 8 实现一个简单的解释型 JVM. 目前零零散散提交了 100 多 commits. 最终的目标是 自举.
目前进度大概 60%, 基本的 ClassFile 解析, 类加载, 字节码执行, 方法调用, 对象实例化, 多态, 接口基本可用.git

0x00 背景

mini-jvm 项目的动机.github

  1. 这有点意思.
  2. 我的平常工做中主要使用 Java, 须要对 JVM 有必定的理解, 然而 Hotspot 源码实在是看不下去.
  3. Learning By Doing.

写此文的目的.bash

  1. 稍加记录, 以备往后回顾,
  2. 广而告之, 以期对 JVM 感兴趣的同窗能了解到有这么一个项目.
  3. 寻道友, 但愿感兴趣的同窗能够联系我, 以期继续完善这个项目.

0x01

在实现的过程当中, 已力保代码简单, 可读, 可测. 目前为止代码 5000 行出头, 窃觉得, 对于想了解 JVM 基本原理的同窗是个不错的入门项目. 在此基础上, 为了便于理解一些概念, 好比基于栈的虚拟机实现原理, 会特地实现一个边缘特性用来快速理解.数据结构

0x02 基于栈的虚拟机基本实现.

对 JVM 字节码执行引擎稍有了解的话, 应该对栈帧有所了解jvm

栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构 栈帧随着方法调用而建立,随着方法结束而销毁,栈帧的存储空间分配在 Java 虚拟机栈中,每一个栈帧拥有本身的局部变量表(Local Variables)操做数栈(Operand Stack)ui

若是尝试用过 javap -v classfile , method 区块亦有所体现.spa

下面看一个简单的例子3d

public class Hello {
  public static int return1() {
    return 1;
  }
}
复制代码

编译并使用code

cat <<EOF > Hello.java
public class Hello {
  public static int return1() {
    return 1;
  }
}
EOF
# 很明显, 若是 return1 方法被调用, 返回结果必定是 1 .
javac Hello.java
javap -v Hello.class
复制代码

输出较长, 只摘抄方法部分以下

public static int return1();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: iconst_1
         1: ireturn
复制代码

stack=1 即此方法栈操做数栈大小为 1 locals=0 即此方法局部变量表大小为 0 args_size 即此方法参数个数为 0

0: iconst_1
1: ireturn
复制代码

这便是该方法的字节码
0: iconst_1 , 表示该方法指令集 0 位置 的指令为 iconst_1 , iconst_1 的含义是 将 int 值 1 push 到操做数栈.
1: ireturn , 表示该方法指令集 1 位置 的指令为 ireturn , ireturn 的含义是, 将当前操做数栈栈顶 int 类型值弹出, 而且把当前栈帧弹出, 并将从操做数栈弹出的 int 类型值 push 到当前栈帧的操做数栈.

相似 iconst_1 这种指令, JVM 规范定义了 200 + 个.

为了方便理解. 项目实现了一个简单的类汇编语言来描述字节码,并解释执行.

return1 1 0 0 
0 iconst_1
1 ireturn
复制代码

对比上方 javap -v 的输出, 去除了一些冗余信息.
下为实际截图

1574438006.png

稍复杂一点的 sum10

1574438135.png

更复杂一点的 sumN

1574438239.png

0x03 尾声

简介到此告一段落, 更多信息可往 github repo 了解.
如有兴趣参与, 务必联系我, 虚左以待.

联系方式
vx: echo "Z3V4aW5na2VfCg==" | base64 -d
mail: echo "YWRtaW5AZ3V4aW5na2UuY29tCg==" | base64 -d

项目地址
github: github.com/guxingke/mi…

相关文章
相关标签/搜索