探索JamVM

qc1iu published this page · Last modified:

之前在C语言陷阱最后提到了JamVm,它是一个十分短小的java虚拟机,对于研究java虚拟机的实现是一个很好的起点。

JamVm很早以前就已经不在维护了,具体可以看它的官网介绍。源码下载地址在sourceforge上。我个人感觉研究jam从它最老的的版本1.0.0下手是个比较好的选择。虽然1.0.0对native的支持不全,而且只支持java4,但是毕竟代码量小(6000+ C),而1.5.4就已经近2W的C了。

2w的C代码其实并没什么,只是对于研究java虚拟机实现来说,没必要。无非是多支持了几条新的虚拟机指令,多支持了一些native,有些模块甚至为了效率牺牲了可读性等等。很多时候代码的复杂度和代码量往往不是线性关系的,而是指数关系不是么?

部署JamVM1.0.0

这个过程中会遇到一些问题,各种问题会导致探索体验变差,其中的几个问题我在之前的文章中提到过,现在系统的总结一下,想要自己折腾的可以忽略后面的全部内容。

下载的源码中包括jam的源码,以及它所需要的classpath0.0.4的源码。这个classpath就是jre,当然现在也已经停止开发了,详情可以参考GNU Classpath

推荐直接在32bit的系统上build,我用的是ubuntu12.04-32bit。

编译classpath0.0.4

classpath用的还是GNU编译3步走,configure,make,make install。不过configure的时候很可能会出错,说找不到javac。根本原因是configure文件需要gcj或者jikes,但是这两个项目现在都die了。一种解决方案是,ubuntu源里面有gcj4.8,先装一个gcj4.8,configure没有问题,但是编译肯定还是一堆的错误。原因是gcj4.8默认是java5,而classpath的源码是java4,所以手动改一下生成的lib/Makefile,用gcj的-fsource和-ftarget参数将版本指定为java1.4就行了。

不想装gcj的可以装openjdk,然后做个软连接,用openjdk的javac冒充gcj。也需要再修改Makefile,原理相同。

当然编译中可能还会有其他问题。

编译jam

如果编译器支持cast-as-lvalue扩展,那么编译jam还是很容易的。不过很遗憾,gcc4.X这个扩展已经没有了。由于JamVM1.0.0是2003年开发的,所以代码里面充斥着将cast-as-lvalue。另外代码里面还存在undefined behavior,这个在C语言陷阱里面提到过,所以这个JamVM我直接修改了一个neojam,不存在cast-as-lvalue和其他的一些gcc4.X的编译错误,以及我已经发现的undefined behavior。

如果还有问题请提issue。