[开源JVM] yvm - 自制Java虚拟机

YVM是用C++写的一个Java虚拟机,现在支持Java大部分功能,以及一个基于标记清除算法的并发垃圾回收器. 不过还有很多bug等待修复。
感兴趣的朋友pull request/fork/star吧。
Github repo
https://github.com/racaljk/yvm
已支持语言特性
高级特性逐步支持中,可以开Issue提议或者直接PR
- Java基本算术运算,流程控制语句,面向对象。
- RTTI
- 字符串拼接(+,+=符号重载)
- 异常处理(可输出stacktrace)
- 创建异步线程
- Synchronized(支持对象锁)
- 垃圾回收(标记清除算法)
构建和运行
- 先决条件
- Boost(>=1.65) 请在CMakeLists.txt中手动配置Boost库位置
- CMake(>=3.5)
- C++14
- gcc/msvc/mingw均可
 
- Boost(>=1.65) 请在
- 老生常谈
$ cd yvm
$ cmake .
$ make -j4
$ make test
$ ./yvm --help
Usage:
    --help                List help documentations and usages.
    --runtime arg         Attach java runtime libraries where yvm would lookup
                        classes at
    --run arg             Program which would be executed soon
You must specify the "runtime" flag to tell yvm where it could find jdk classes, and also program name is required.
$ ./yvm --runtime=C:\Users\Cthulhu\Desktop\yvm\bytecode ydk.test.QuickSort
运行效果
- helloworld
  
  
- 快速排序
  
  
- and more see its github repository readme.md...
开发文档
1. 从字节码到对象
MethodArea负责管理字节码到JavaClass的完整生命周期。MethodArea的方法是自解释的:
class MethodArea {
public:
    // 方法区需要从运行时目录中搜索相关的*.class文件
    MethodArea(const vector<string>& libPaths);
    ~MethodArea();
    // 查看一个类是否存在
    JavaClass* findJavaClass(const string& jcName);
    //加载jcName类
    bool loadJavaClass(const string& jcName);
    //移除jcName(该方法用于垃圾回收器)
    bool removeJavaClass(const string& jcName);
    //链接jcName类,初始化static字段
    void linkJavaClass(const string& jcName);
    //初始化jcName,初始化静态字段,调用static{}
    void initJavaClass(CodeExecution& exec, const string& jcName);
public:
    //辅助方法,如果不存在jcName则加载
    JavaClass* loadClassIfAbsent(const string& jcName);
    //如果未链接jcName则链接
    void linkClassIfAbsent(const string& jcName);
    //如果未初始化jcName则初始化
    void initClassIfAbsent(CodeExecution& exec, const string& jcName);
}
假设磁盘存在一个Test.class文件,它会经历如下过程:
Test.class[磁盘中]-> loadJavaClass("Test.class")[内存中] -> linkJavaClass("Test.class")->initJavaClass("Test.class")
现在虚拟机就可以使用这个JavaClass创建对应的对象了:
// yrt 是全局运行时对象,ma表示方法区模块,jheap表示堆模块
JavaClass* testClass = yrt.ma->findJavaClass("Test.class");
JObject* testInstance = yrt.jheap->createObject(*testClass);
2.1 对象内部构造
虚拟机执行时栈上存放的都是JObject,它的结构如下:
struct JObject {
    std::size_t offset = 0;
    const JavaClass* jc{};
};
offset唯一代表一个对象,所有在堆上面的操作都需要这个offset。jc指向对象的Class表示。
堆中的对象是按照<offset,fields>方式进行存放的:
[1]  ->  [field_a, field_b, field_c]
[2]  ->  []
[3]  ->  [field_a,field_b]
[4]  ->  [field_a]
[..] ->  [...]
只要我们持有offset,就可以查找/添加/删除对应的field
数组几乎和上面类似,只是多了长度,少了Class指针
struct JArray {
    int length = 0;
    std::size_t offset = 0;
};
[1]  ->   <3, [field_a, field_b, field_c]>
[2]  ->   <0, []>
[3]  ->   <2, [field_a,field_b]>
[4]  ->   <1, [field_a]>
[..] ->   <..,[...]>
2.2 从对象创建到消亡
上面提到,对象持有一个offset和jc,其中jc表示的JavaClass是由MethodArea负责管理的,offset则是由JavaHeap负责管理。JavaHeap提供了大量API,这里选取的是最重要的:
class JavaHeap {
public:
    //创建对象和数组
    JObject* createObject(const JavaClass& javaClass);
    JArray* createObjectArray(const JavaClass& jc, int length);
    //获取对象字段
    auto getFieldByName(const JavaClass* jc, const string& name,
                        const string& descriptor, JObject* object);
    //设置对象字段
    void putFieldByName(const JavaClass* jc, const string& name,
                        const string& descriptor, JObject* object,
                        JType* value);
    //设置数组元素
    void putElement(const JArray& array, size_t index, JType* value);
    //获取数组元素
    auto getElement(const JArray& array, size_t index);
    //移除对象和数组
    void removeArray(size_t offset;
    void removeObject(size_t offset);
};
还是Test.class那个例子,假设对应的Test.java构造如下:
public class Test{
    public int k;
    private String hello;
}
在第一步我们已经获取到了Test类在虚拟机中的类表示以及对象表示,现在就可以对类的字段进行操作了:
const JavaClass* testClass = yrt.ma->findJavaClass("Test.class");
JObject* testInstance = yrt.jheap->createObject(*testClass);
//获取hello字段
JObject*  helloField = yrt.jheap->getFieldByName(testClass,"hello","Ljava/lang/String;",testInstance);
//设置k字段
yrt.jheap->putFieldByName(testClass,"k","I",testInstance);
Ⅰ. 关于JDK
部分JDK类是JVM运行攸关的,但由于JDK比较复杂不便于初期开发,所以这里用重写过的JDK代替,源码参见javaclass目录,可以使用compilejava.bat进行编译,编译后*.class文件位于bytecode.
目前重写过的JDK类有:
- java.lang.String
- java.lang.StringBuilder
- java.lang.Throwable
- java.lang.Math(::random())
- java.lang.Runnable
- java.lang.Thread
Wiki和源码中有很多详细的开发文档,如果想探索关于YVM的更多内容,请移步浏览.
License
所有代码基于MIT协议
[开源JVM] yvm - 自制Java虚拟机的更多相关文章
- [开源] yvm - 自制Java虚拟机
		项目地址 : https://github.com/racaljk/yvm 虚拟机现在已可运行(不过还有很多待发现待修复的bugs),已支持语言特性有: Java基本算术运算,流程控制语句,面向对象. ... 
- 自制Java虚拟机(四)-对象、new、invokespecial
		自制Java虚拟机(四)-对象.new.invokespecial 一.对象的表示 刚开始学Java的时候,图书馆各种教程,书名往往都是“Java面向对象高级编程”,通常作者都会与C++做个比较,列出 ... 
- [转]JVM内幕:Java虚拟机详解
		本文由 ImportNew - 挖坑的张师傅 翻译自 jamesdbloom.欢迎加入翻译小组.转载请见文末要求. 这篇文章解释了Java 虚拟机(JVM)的内部架构.下图显示了遵守Java SE 7 ... 
- JVM内幕:Java虚拟机详解
		这篇文章解释了Java 虚拟机(JVM)的内部架构.下图显示了遵守 Java SE 7 规范的典型的 JVM 核心内部组件. 上图显示的组件分两个章节解释.第一章讨论针对每个线程创建的组件,第二章节讨 ... 
- JVM原理二----JAVA虚拟机体系结构
		组成: 指令集,寄存器,栈,无用单元收集(GC),方法区域.JAVA核心 1,指令集:这个不太清楚 2,寄存器:和处理器中的寄存器类似 pc:Java程序计数器. optop:指向*作数栈顶端的指针. ... 
- Java虚拟机(一):JVM简介
		JVM简介 Java虚拟机(JVM)是由Java虚拟机规范定义的,其上运行的是字节码指令集.这种字节码指令集包含一个字节的操作码(opcode),零至多个操作数(oprand),虚拟机规范明确定义了每 ... 
- Java虚拟机(一):JVM内存结构
		所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ... 
- Java虚拟机规范----JVM体系结构
		一.Java平台的结构图 二.JVM与JRE.JDK关系? JVM:Java Virtual Machine(Java虚拟机),负责执行符合规范的Class文件 JRE:Java Runtime En ... 
- 关于Java虚拟机JVM的简单了解
		JVM主要功能 Java是一种高级编程语言. 用高级语言编写的程序不能直接在任何机器上运行. 首先,需要将其翻译成特定的机器语言,javac编译器就专门来干这个事儿的,它把Java程序(含有的.jav ... 
随机推荐
- 02- 画文字和图片-------------之前写的那个微博项目,可以试试用画图片的方式来处理,这样应该比UILabel 代码少点,一会试试
			1.画图片 - (void)drawRect:(CGRect)rect { // Drawing code UIImage *image = [UIImage imageNamed:@"pa ... 
- 本地yum源构建以及Docker离线安装
			Docker离线安装以及本地yum源构建 在docker的使用过程中有时候会遇到一些私有化部署的问题,就是在一些无法上网的机器上面安装使用dokcer,这就引出了docker的离线安装的问题,dock ... 
- 商业级别Fortify白盒神器介绍与使用分析
			转自:http://www.freebuf.com/sectool/95683.html 什么是fortify它又能干些什么? 答:fottify全名叫:Fortify SCA ,是HP的产品 ,是一 ... 
- OpenCV学习记录(一):使用haar分类器进行人脸识别                                                                                                         标签:               opencv脸部识别c++                                            2017-07-03 15:59             26人阅读
			OpenCV支持的目标检测的方法是利用样本的Haar特征进行的分类器训练,得到的级联boosted分类器(Cascade Classification).OpenCV2之后的C++接口除了Haar特征 ... 
- 点云数据保存为pcd文件_pcd_write.cpp
			#include <iostream>#include <pcl/io/pcd_io.h>#include <pcl/point_types.h> int main ... 
- ubuntu 16.04 nfs服务的搭建
			nfs服务是实现Linux和Linux之间的文件共享,nfs服务的搭建比较简单. 现在介绍如何在ubuntu16.04系统中搭建nfs服务,ubuntu的搭建比红帽的还要简单. 1.安装nfs服务 s ... 
- System.Reflection.Emit摘记
			动态类型在.net中都是用什么类型来表示的.程序集:System.Reflection.Emit.AssemblyBuilder(定义并表示动态程序集)构造函数:System.Reflection.E ... 
- functions函数插件的定义和使用
			创建Smarty插件:在插件目录(plugins)里新建文件 类型.插件名.php文件,然后插件方法名字书写规范: smarty_类型_插件名([...]){}在模板(tpl文件)中调用插件时格式{插 ... 
- python json.dumps输出中文问题
			json.dumps 输出的中文是"\u6211\u662f"格式的,输出中文需要指定ensure_ascii=False. json.dumps(actual,ensure_as ... 
- Ceph介绍
			1. 介绍 云硬盘是IaaS云平台的重要组成部分,云硬盘给虚拟机提供了持久的块存储设备.目前的AWS 的EBS(Elastic Block store)给Amazon的EC2实例提供了高可用高可靠的块 ... 
