依星源码资源网,依星资源网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

【好消息,好消息,好消息】VIP会员可以发表文章赚积分啦 !
查看: 56|回复: 0

用 C++ 实现了一个小型的 jvm

[复制链接] 主动推送

1万

主题

1万

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
12071
发表于 2024-10-16 13:07:13 | 显示全部楼层 |阅读模式
用 C++ 实现了一个小型的 jvm
一开始只是想写一个 java 的 class file parser。后来把这东西变成了一个 tool,请左转看我的小工具 javap。后来看到
@racaljk
同学用 java 实现了一个小虚拟机,感觉很有意思,遂学习了一波规范,然后写了个 C++ 的。
// 注:原先编辑的文章中有类似项目小标题。不过想想还是不太好,因此去掉了。但是依然对其他几位有兴趣的同好的代码思路带来的启迪表示感激。
具体
我的 wind jvm 也就是个小玩具。代码总量用 cloc 去一下水分,也就 15k 左右。一共花了两个月代码时间,其实还有一个月是在学习各种乱七八糟的支持项目的知识。还 reference 了各种东西,列举如下:
  • jvm8 spec
  • 周志明大大的《深入理解 java 虚拟机》
  • 陈涛大大的《HotSpot 实战》
  • (日)中村成洋先生的《垃圾回收的算法与实现》(中译)
  • 等等。重要的还有一堆网络资源。比如 R大的 hllvm 论坛:hllvm论坛~
那么说下打开方式
我的 README 上都有写,在这里重写一遍。
  • 首先我只支持 linux 和 mac。因为底层用了各种操作系统函数,pthread,stat 啥的。我的机器是 mac,所以就不支持 Windows 了。然后呢,我们需要 boost 库。用 brew 安装和 apt-get 啥的,yum 啥的都行。mac 就是 [size=0.9em]brew install boost,然后 ubuntu 应该是 [size=0.9em]sudo apt-get install libboost-all-dev
  • 这样我们就有了 boost 支持了。于是我们应该去 Makefile 修改一下,因为我配置的是我机器的环境,而且没用 cmake。所以要手动修改,把我机器上的 boost 路径目录换成你的就可以了。比如如果是 mac 的话,把 ifeq 中的 [size=0.9em]$(CC) $(LINK_FLAGS) -L/usr/local/Cellar/boost/1.60.0_2/lib/ .... 里边的目录换成你自己的就行。如果是 linux,就把 else 中的 [size=0.9em]$(CC) $(LINK_FLAGS) -L/usr/lib/x86_64-linux-gnu/ 换成你自己的。不过如果是 ubuntu,八成不需要改,因为目录的版本无关。其他的 linux 就不知道了。
  • 然后呢,你需要知道你的 jdk class 文件路径。mac 上,一般在 [size=0.9em]/Library/Java/JavaVirtualMachines/jdk1.8xxx.jdk/Contents/Home/jre/lib/ 下的 rt.jar 文件。如果是 linux,一般在 [size=0.9em]/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ 下。配置到 config.xml 中相应位置就可以了。
  • 于是应该就完事了。直接跑 make -j 8 啥的 8 线程编译就可以。当然如果你是虚拟机,虚拟内存没配置够的话就算了,直接跑 make -j 2 或者 make -j 3 这种就行了。
  • 之后 [size=0.9em]bin 目录会出现 [size=0.9em]wind_jvm 这个 executable file。注意:一定要在 [size=0.9em]wind_jvm/ 目录运行 [size=0.9em]./bin/wind_jvm Test1 这样的命令。因为内部我的 system lib path 是通过当前路径来获取的。如果不在 [size=0.9em]wind_jvm/ 目录下跑,就应该会报错。然后我给了十几个 TestX.java 文件,执行 [size=0.9em]make test 就能编译。有一个 Test7.java 是不行的。那个只有 debug version jvm 的工具才能编译。所以我编译好了直接放上去了。然后运行 [size=0.9em]./bin/wind_jvm Test1 这种命令就好。不加 [size=0.9em].class 后缀,参数必须有且仅有一个。
  • 然后就可以玩了。不过只支持特定实现好的库,你要 socket 什么的都是没有的。不过日后实现看情况可以往上加,你也可以来 pull request 哦。
  • 如果有 issue 请在 github 上上传 issue。
特性支持
  • 完整的 ClassFileParser。那个 tool 的地址我已经刚才写过了。这东西才 3k 行多一点而已。
  • 支持大部分常用反射机制。其他的是我没写的。因为太多了......不过想写的话肯定是有的。具体在 [size=0.9em]src/native/sun_reflect_Reflection.hpp(cpp)[size=0.9em]src/native/sun_reflect_NativeConstructorAccessorImpl.hpp(cpp) 等等文件中。
  • 支持底层的 Unsafe 类中的大部分。如果想要支持 jdk 类库,这个类是必须要写且必须实现的。这个类可以添加 java 不能而 C++ 能的指针操作。必须强行交换两个对象什么的。当然,还需要有少量 CAS support。并发非常必要。
  • 支持简单多线程。Thread 类的底层方法是通过操作系统级别的线程支持的。比如 pthread 库。
  • 支持异常机制。stack unwind 栈回溯,athrow 以及可以 catch 字节码已经处理好的异常表。Test7.java 就是测试多线程异常的。
  • 支持 GC。parallel GC 支持的保证是 stop-the-world (调 bug 可是好长好长时间好痛苦哇),使用了 GC-Root 算法,以及 GC 复制算法。见:gc.cpp......虽然代码量不大确是调试时间最长最难受的部分......毕竟这不是单线程 GC,是多线程的......不过我的实现肯定也是 too young 的,因为并没有各种菊苣的 paper 的支持。
  • 部分支持 lambda,比如简单的 invokedynamic 类似 [size=0.9em]Thread t = new Thread(() -> System.out.println("hello world"));,Test4,5,6,8,11,13 是测试 lambda 和 invoke(MethodHandle) 的。不过很遗憾这一部分理解有些跟不上,虽然支持是比较容易,但是想要理解类库究竟是怎么实现 lambda,还需要积累和进一步研究。因此只能支持部分。[注:部分测试用例 from network]。具体实现代码请见:invokedynamic。当然不可能只有这点。这里是核心部分。还有待支持更多。
  • 字节码方面,支持绝大多数,没用到的就没写(怕写错),wide 指令这种,我是没加的。
实现细节
  • 和 openjdk 一样的,klass oop 二分模型。
  • 解释型。完全在解释 bytecode。因此效率上肯定差强人意。
  • 按照真正的 jvm 跑 class 文件的流程运行(几乎)。初始化 mirror,初始化基础类,使用 C++ 实现的 bootstraploader,进而调用 java 的 AppClassLoader 来加载 main class。
  • 每个线程配上了不同的颜色(,方便观看(其实更重要的是方便调试哇。(笑)
  • 等等。细节太多了。如果你想看更多的细节,下文有字节码执行的流程输出。
糟粕
  • 一开始什么也不会的时候,用字符串查找类......这是特别悲伤的设计。严重拖慢速度,历史遗留问题。
  • 有时跑 Test7 这种多线程测试用例碰到异常的时候,最后会段错误。其实是完全可以解决的。用 pthread_cancel 配上 pthread_join 就可以完全解决。不过一开始的设计是没考虑到这么多,直接把所有线程 detach 了。如果要改,势必代码的形状会特别悲伤。所以左思右想还是维持原状,并不影响运行结果。其实这样是并不对的,java 要求某一线程抛异常,不会影响其他线程的执行。其实真正的实现是要用 join 的。
  • 等等。
输出细节
如果想要开启更多的细节,可以在 Makefile 中修改,原本是 CPP_FLAGS := -std=c++14 -O3 -pg,我在后边写了一个加上 -DBYTECODE_DEBUG -DDEBUG 的,启用这个就可以启用所有的字节码调试代码。引用一张月初放在博客上的图: 题图就是开启宏之后的输出结果。
如果还要看 classfile 的文件 parse,运行时常量池的解析,以及字符串池的常量字符串,可以打开 -DKLASS_DEBUG -DPOOL_DEBUG -DSTRING_DEBUG 宏,然后重新编译就好。
不过!如果这么打开,由于一开始初始化虚拟机,需要加载各种类,需要跑各种字节码,输出会是巨量的。没记错的话跑一个 hello world 貌似就要上十w的字节码执行量吧。因为我是解释型,自然执行的机器码比这还多;如果是编译型,那就快了。所以如果发现终端吃不消,请及时关闭。后期由于字节码输出量巨大,我从来都是关闭这些宏的,只看结果忽略执行过程。

用 C++ 实现了一个小型的 jvm

用 C++ 实现了一个小型的 jvm


游客,本帖隐藏的内容需要积分高于 2 才可浏览,您当前积分为 0

提取码下载:
文件名称:提取码下载.txt 
下载次数:0  文件大小:12 Bytes  售价:20金钱 [记录]
下载权限: 不限 [购买VIP]   [充值]   [在线充值]   【VIP会员5折;永久VIP免费】
安全检测,请放心下载





相关帖子

扫码关注微信公众号,及时获取最新资源信息!下载附件优惠VIP会员5折;永久VIP免费
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
1、本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
2、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,请勿任何商业目的与商业用途。
3、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4、论坛的所有内容都不保证其准确性,完整性,有效性,由于源码具有复制性,一经售出,概不退换。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
5、用户使用本网站必须遵守适用的法律法规,对于用户违法使用本站非法运营而引起的一切责任,由用户自行承担
6、本站所有资源来自互联网转载,版权归原著所有,用户访问和使用本站的条件是必须接受本站“免责声明”,如果不遵守,请勿访问或使用本网站
7、本站使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负责,本站不承担任何责任。
8、凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。
9、本站以《2013 中华人民共和国计算机软件保护条例》第二章 “软件著作权” 第十七条为原则:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。若有学员需要商用本站资源,请务必联系版权方购买正版授权!
10、本网站如无意中侵犯了某个企业或个人的知识产权,请来信【站长信箱312337667@qq.com】告之,本站将立即删除。
郑重声明:
本站所有资源仅供用户本地电脑学习源代码的内含设计思想和原理,禁止任何其他用途!
本站所有资源、教程来自互联网转载,仅供学习交流,不得商业运营资源,不确保资源完整性,图片和资源仅供参考,不提供任何技术服务。
本站资源仅供本地编辑研究学习参考,禁止未经资源商正版授权参与任何商业行为,违法行为!如需商业请购买各资源商正版授权
本站仅收集资源,提供用户自学研究使用,本站不存在私自接受协助用户架设游戏或资源,非法运营资源行为。
 
在线客服
点击这里给我发消息 点击这里给我发消息 点击这里给我发消息
售前咨询热线
312337667

微信扫一扫,私享最新原创实用干货

QQ|免责声明|小黑屋|依星资源网 ( 鲁ICP备2021043233号-3 )|网站地图

GMT+8, 2024-11-24 04:06

Powered by Net188.com X3.4

邮箱:312337667@qq.com 客服QQ:312337667(工作时间:9:00~21:00)

快速回复 返回顶部 返回列表