[讨论] junit可以在jvm.go上跑起来了

zxh1 2015-03-04

jvm.go是我最近用Go语言写的一个JVM。大约花了一两周的时间,HelloWorld就可以打印出来了,但是还很不完善。这里有一些简单的介绍。又花了大概一个月的时间,jvm.go有了实质性的进展:下面的junit测试也可以跑出结果了!
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class UnitTests {
    
    @Test
    public void test() {
        Assert.assertEquals(2, 1 + 1);
    }
    
    public static void main(String[] args) {
        Result result = JUnitCore.runClasses(UnitTests.class);
        if (result.getFailureCount() > 0) {
            for (Failure f : result.getFailures()) {
                System.out.println(f);
            }
        } else {
            System.out.println("OK!");
        }
    }
    
}

不过现在jvm.go离完整的JVM仍然差的很远,很多基本功能还没有完全实现,比如文件操作,多线程,网络,等等。发表这个话题,希望感兴趣的人可以知道这个项目
RednaxelaFX 2015-03-14
不错!我去微博上宣传一下~
联动微博:http://www.weibo.com/2164690772/C8uqT6FtK
联动Hacker News帖:https://news.ycombinator.com/item?id=9203045
很明显golang-nuts讨论组里也有人留意到这个项目了:https://groups.google.com/d/msg/golang-nuts/kPmSoDh_Gb0/BEehHV6UhC8J
ZHH2009 2015-03-14
鼓励一下,

不过,等你花了半年时间后,你不一定能把JVM规范中定义的东西都实现了(这还仅仅是规范)

若是你想研究HotSpot VM,前两月估计比较痛苦,同样半年后达到的水平也许不会比你用go写半年jvm低的,
zxh1 2015-03-15
谢谢大家的鼓励。在RednaxelaFX宣传之后,jvm.go一下收到了很多star,大大出乎了我的意料。不过压力也很大,毕竟是写着玩的项目,代码和注释写的可能都没那么好。而且原本也没想过究竟要实现到什么地步,写一点算一点。

现在我最大的疑惑是,使用Oracle(或OpenJDK)的rt.jar是否有问题?甚至是否会被追究法律责任?希望对这方面有了解的人能给一些建议。
RednaxelaFX 2015-03-16
zxh1 写道
现在我最大的疑惑是,使用Oracle(或OpenJDK)的rt.jar是否有问题?甚至是否会被追究法律责任?希望对这方面有了解的人能给一些建议。

用OpenJDK的rt.jar完全没问题,因为OpenJDK的Java源码都由Classpath Exception覆盖,不影响JVM的许可证。有不少开源JVM用OpenJDK的class library,而它们的许可证各有各不同。JamVM、CACAO VM、Jikes RVM等等。

但是跟用户说“你要自己去Oracle JDK里拷贝一份rt.jar过来”,这就不行了。内容上OpenJDK8和Oracle JDK8的rt.jar几乎一样,但是许可证不同,前者是GPLv2+CE,后者则不是开源的不能乱用。

楼主可以给jvm.go选一个合适的开源许可证,并将rt.jar的依赖改为OpenJDK的,这样就没问题了。

最好的情况下,jvm.go应该做成一个能直接替换HotSpot VM扔进OpenJDK的目录结构就能跑的JVM。有不少别的VM都能做到这点,例如JamVM就是IcedTea的备选JVM。

稍微看了下jvm.go的代码然后温习了一下我的Go知识⋯想起了当年为啥我学习Go的时候试着用它写JVM但是很快就放弃了——很多地方用Go写简直比用Java写还蛋疼。要想实现得高效的话用纯Go太麻烦了。
zxh1 2015-03-16
其实写这个小玩意的本意就两个:1是学习Go语言,2是理解JVM内部工作原理。对于我来说,这两个目的都达到了。如果这份代码能给别的有同样想法的人带来一点帮助,那就更好了。

选择直接使用Go语言的GC功能,这个JVM就不用自己实现GC,难度已经大大降低了。再加上自己没有能力实现JIT,所以这个JVM其实写起来难度并不大,照着JVM规范把各种概念翻译成Go代码就可以了。大部分的时间实际上是花在了摆弄rt.jar上。现在最大的难度和挑战是完整实现多线程和类加载器,我到现在也不知道能否最终实现它们。

项目一开始就是选择OpenJDK的rt.jar的,但是后来发现它和Oracle的rt.jar还是有一些差别的,这样我用NetBeans直接进入源代码就很不方便。不得已临时换成了Oracle的rt.jar。这几天就会退回到OpenJDK,照着RednaxelaFX给的方向去前进。

至于Go语言,我觉得它和Java还是有很大不同的,不宜在一起做比较。但了解不同的语言,和不同语言解决同样问题的方式,对程序员来说是有好处的。对个人来说,喜欢Java就用Java,喜欢C就用C,喜欢Go就用Go。能解决问题,能提高自己就好了。
RednaxelaFX 2015-03-17
zxh1 写道
选择直接使用Go语言的GC功能,这个JVM就不用自己实现GC,难度已经大大降低了。再加上自己没有能力实现JIT,所以这个JVM其实写起来难度并不大,照着JVM规范把各种概念翻译成Go代码就可以了。大部分的时间实际上是花在了摆弄rt.jar上。现在最大的难度和挑战是完整实现多线程和类加载器,我到现在也不知道能否最终实现它们。

多线程在现在这个模型上最容易的实现方式就是用green-thread——自己模拟“线程”的概念而不是真的用goroutine或者说操作系统线程啥的。这样不用考虑那么多麻烦事。
在解释器循环里记录运行了多少条字节码,然后每隔一定数量的字节码就切换一次“线程”。涉及blocking I/O的操作尽量用异步I/O来模拟,让I/O发生时解释器还可以运行别的Java线程。

类加载器楼主觉得难是难在什么地方?我并没有觉得类加载器会很难诶…

剩下有些东西应该做的,是weak reference的支持和JNI的完整支持。
前者要想在Go里模拟应该会非常非常麻烦。Go自己的GC并不支持weak reference的概念,要模拟的话…我还没想到啥好法子。
后者其实应该不做,就是代码量会比较大。很大嗯。需要用Go实现JNI的内部支持,然后用cgo来export出C API。

话说源码里rtda是啥的缩写?RunTime Data Access?
zxh1 2015-03-17
这个项目实际上就是个比较大的Go语言练习,希望尽可能用到多一些的Go语言特性,所以自己还是想用goroutine来实现Java线程。现在只是大致把Java线程映射成了goroutine,如何完整实现Java内存模型,还得边写边想,感觉比较麻烦,也比较难。

觉得类加载难,可能是因为我对类加载器了解的较少。比如说指令集,JVM规范里有详细说明,照着实现就行。但是类加载器,JVM规范没有特别详细的介绍。自己到现在脑袋里也还没有一个特别清晰的认识。现在基本就是想通过把Bootstrap类加载器,App/System类加载器,UrlClassLoader等实现来最终理解类加载器。但最近时间比较少,进展缓慢。

weak reference想过,觉得没法实现。JNI就压根还没考虑过

rtda是RunTime Data Area的意思。名字起的确实有点差,可是想不出更好(又短)的名字了。Go的包是不能像Java那样循环引用的,这在很大程度上影响了代码包结构的组织和代码的可读性。自己某种程度上还是按照Java的思想,在用Go写程序。很多习惯很难改。
RednaxelaFX 2015-03-17
实现JNI(以及一套类似JNI的JVM私有的native函数API)可以比较方便的利用上OpenJDK类库的完整功能。

例如说类加载器。像HotSpot VM的话,只有bootstrap class loader是在VM里实现的;上面的ClassLoader都是在Java代码里实现的,包括extension class loader、system class loader等。它们通过defineClass()这个入口与JVM交互。JVM只需为上面的ClassLoader实现defineClass()即可。
在需要触发类加载时,如果“当前类加载器”不是bootstrap class loader,那么JVM需要调用ClassLoader.loadClass()去找到类文件的内容,等ClassLoader反过来调用defineClass()回到JVM里完成类加载动作。

要想充分利用OpenJDK的Java代码里已经实现好的ExtClassLoader和AppClassLoader类的话,就得相应的做好JNI和JVM API部分的实现。这样开头是有点麻烦,但后面事半功倍。
zxh1 2015-03-17
但是类加载器,感觉并没有那么简单。比如ClassLoader这个类,并不止defineClass()一个native方法,还有findBootstrapClass()等多个。不过这个我慢慢研究吧

如果我想得到一份OpenJDK的rt.jar(或者jre8的zip包),最好的地方是哪里呢?我找到了以下这几个地方:
https://jdk8.java.net/download.html
https://github.com/alexkasko/openjdk-unofficial-builds
http://www.azulsystems.com/products/zulu/downloads

github这个项目应该是很久没维护了。觉得zulu挺不错的,提供了zip压缩包。不知是否可以直接使用。
Global site tag (gtag.js) - Google Analytics