Learning By Doing.
最近开了个新坑, 目的是用 Java 8 实现一个简单的解释型 JVM. 目前零零散散提交了 100 多 commits. 最终的目标是 自举.
目前进度大概 60%, 基本的 ClassFile 解析, 类加载, 字节码执行, 方法调用, 对象实例化, 多态, 接口基本可用.
mini-jvm 项目的目的.
写此文的目的.
在实现的过程中, 已力保代码简单, 可读, 可测. 目前为止代码 5000 行出头, 窃以为, 对于想了解 JVM 基本原理的同学是个不错的入门项目.
在此基础上, 为了便于理解一些概念, 比如基于栈的虚拟机实现原理, 会特意实现一个边缘特性用来快速理解.
对 JVM 字节码执行引擎稍有了解的话, 应该对栈帧有所了解
栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构 栈帧随着方法调用而创建,随着方法结束而销毁,栈帧的存储空间分配在 Java 虚拟机栈中,每个栈帧拥有自己的局部变量表(Local Variables)操作数栈(Operand Stack)
如果尝试用过 javap -v classfile , method 区块亦有所体现.
下面看一个简单的例子
public class Hello { public static int return1() { return 1; } }
编译并使用
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 的输出, 去除了一些冗余信息.
下为实际截图
稍复杂一点的 sum10
更复杂一点的 sumN
简介到此告一段落, 更多信息可往 github repo 了解.
若有兴趣参与, 务必联系我, 虚左以待.
联系方式
vx:echo "Z3V4aW5na2VfCg==" | base64 -d
mail: echo "YWRtaW5AZ3V4aW5na2UuY29tCg==" | base64 -d
项目地址
github: https://github.com/guxingke/mini-jvm