Crazy knowledge base

GNU的Java编译器GCJ

为什么GNU要搞出一个Java的编译和解释器来呢?其大致有以下几点:
a)传统的JVM太慢了,因为它解释的是class文件中的bytecode。这种方法实在是太慢了。
b)为了优化性能,引入了JIT(Just-In-Time),JIT会分析代码,找出那些被反复调用到一定次数的方法和函数,然后直接把这个方法直接处理成汇编machine code,以后就直接运行机器码了。
c)当然,JIT也有问题,一个是startup overhead,就是说启动的时候有点过分了,表现为时间慢,并且,每次编译后,都需要JIT重新做来过。另一个问题是JIT比较耗费空间。
d)传统的java还有一个比较扯的问题,就是布署起来太麻烦了,需要有N个jar文件,而不是一个可执行文件。并且,Java需要一个很肥大的运行环境。另外,在java和c/c++之间的调用慢得令人受不了。
上述的东西是催生出现gcj的原因,GNU用了Ahead-of-Time Compilation来形容GCJ。GNU对GCJ的出现在理由做了下面的说明:
a)GCC本来可以编译多种程序语言,所以,把java整进来也是一件make sense(合乎逻辑)的事情。

b)Java的编译是一件非常简单的事情,因为没有C++的模板和预编译器,而且system type, object model 和 exception handling 也很简单。所以,这对于擅长编译技术的GNU来说,从编译方面优化Java的性能是一些很简单的事。
c)gcj会对java程序做N多的优化工作,比如:common sub-expression elimination, strength reduction, loop optimization 和 register allocation。在优化方面,是GCJ牛还是JIT牛,存在一些较大的争论。对于JIT来说,它可以裁剪和做适时优化,因为是在运行时。 Sun的HotSpot技术是其中比较牛的技术,但gcj的技术也不一定就比JIT差。
d)对于使用gcj的人来说,最大的一个好处就是startup speed和内存空间使用率。启动JVM或JIT会肖耗很大的内存,例如:NetBean启动就需要74M的内存(什么事也没有干), JEmacs使用Swing,一启动就是26M,而XEmacs只有8M(这些数据是比较老的了,大约在2003年的数据)。
e)当GCJ刚出道时,有人比较了Kawa Test Suite在GCJ和JDK1.3.1下的运行比较。结果是,GCJ速度比Sun的JIT快两倍,因为GCJ比Sun的JDK少了一半以上的内存访问未命中的事情,也就是说少了一半的内存换页。并且,实际运行过程中,也少了25%的内存使用。
f)最后,GCJ用的是一个so的库来做编译,他可以把.java的程序直接编译成.o文件和可执行文件。并且用gdb调试。
用GCJ编译Java程序很简单,关于编译成.o和执成文件,如下所示:
gcj -c -g -O MyJavaProg.java
gcj -g –main=MyJavaProg -o MyJavaProg MyJavaProg.o
很明显,基本上就是gcc的语法。当然,你也可以一步编译出可执行文件:
gcj -g –main=MyJavaProg -o MyJavaProg MyJavaProg.java
其中,使用-g参数表示加入调试信息,这对于调试时相当重要。不然,无法看到实际的源码和函数。而关于–main参数,意思是指定main函数所在的Java类。
如果你需要使用makefile,想使用类似于CFLAGS这样的变量,我们可以使用GCJFLAGS这个变量名。

GNU的Java编译器GCJ

发表评论

滚动到顶部