服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

网友分享:认识java jvm与c/c++的执行效率 (1)

【赛迪网-技术论坛整理】认为java不能写jvm是完全错误的。jnode是一个用java写的开源操作系统,他里面的jvm就是用java写的。这个操作系统现在有几十兆,其中99%的代码是用java编写,其中只有一个极小的“操作系统引导程序”是用汇编写的,我们暂时称之为booter.exe,大小为几kb。

booter.exe的作用就是将用java写的jvm编译并装入内存,简单的说就是将jvm.class编译成jvm.exe(jvm.exe也是内存中的二进制代码,并不是真实存在的文件,我暂时称之为jvm.exe),这个过程花了5秒种。

在这个操作系统中,汇编程序只能执行1秒钟。之后汇编程序就退出内存,也再也不执行了。内存中只剩下用java写的jvm.exe。

之后所有的操作都有jvm.exe来进行,jvm.exe负责将其它的abc.class、def.class等等编译成abc.exe、def.exe......操作系统正式启动。

jnode的官方网站上有java写的jvm的性能和sun的jvm进行性能比较的结果,jnode中用java写的jvm竟然能比sun公司用c++写的jvm还快!

结果如下:

运行评测程序arithopt时:

jnode :20ms*

sun j2sdk :30ms**

上面jnode中用java写的jvm与sun j2sdk的用c++写的jvm的比较是在pentium4/2ghz with 1gb of memory上比较的。

其实,无论是c++,java,vb,delphi还是perl,他们最终在cpu中执行时都是“二进制代码”,没有本质区别,他们的差别就在于:不同的编译器编译出来的“二进制代码”的优化程度不同。用程序员直接写出的汇编由于没有进行深入的优化,很难达到其它用java/c++/delph/vb编译器的优化程度,所以我说:手写汇编的速度达不到c++/java的速度,实质就是说:“手写汇编再编译出来的‘二进制代码’的优化程度没有用c++/java编译器编译出来的‘二进制代码’的优化程度高”。

底层用c++或汇编来写,并不是因为他们更快,而是因为他们更节省内存、操作硬件更方便,vb是一种解释语言,它的内存占用量也很大,而且vb中直接操作内存等硬件的方法并不多,而且c++已经有许多已经成型的类库,用c++写jvm明显比vb强。如果你“感觉”eclipse或永中慢就认定java慢,那么大家“感觉”windowsxp慢是不是大家就应该认定 "c++慢 "呢?。谁快谁慢,拿数据说话吧。

另外,不要因为某些java程序启动慢就认定java慢。这除了因为上面说的原因外,还因为:

c++启动较快也不全是因为c++本身的原因,许多c++写的软件所需的一些.exe和.dll在操作系统启动时就已经启动了(比如和窗口相关的一些.dll)。

.net程序启动较快就是因为.net的虚拟机其实在操作系统启动时就已经启动了。

而其它一些大型软件如microsoft word启动较快,就是因为操作系统启动时就已经启动了和word相关的一些服务和功能。

当然对于能直接支持java bytecode的cpu,booter.exe也可以不需要,只要有个booter.class就可以,这样,整个操作系统就100%都是java写的了。

还有,就算在不支持java bytecode的cpu上,也可以用java来写booter.exe。

原理很简单:写个booter.java,将它编译成booter.class,再用java写个“.class to .exe编译器”,将booter.class编译成booter.exe,这次,booter.exe不仅存在于内存中,还可以将它写到硬盘上。这用java编译出来的booter.exe所有的功能都和用汇编写的booter.exe完全一样。

从此,我们就得到了一个“100%”的纯java操作系统。

完全可以用delphi写一个c++编译器,再用这个编译器去编译abc.cpp的源代码,难道编译出来的abc.exe就变成了delphi程序吗?一个二进制代码是用什么语言写成的,是由“它是由什么编译器编译出来”决定的,而不是由“它的编译器是由什么语言写成的”决定的。

所以java程序不是c++程序,因为无论java的编译器是用vb、perl、c++、还是汇编写成的,只要编译编译的是abc.java的源代码,这就是个java程序。

举个例子,有4种java编译器。一种是用vb写成的,一种是用c++写成的,一种是用delphi写成的,一种是用perl写成的。他们都去编译abc.java的源代码:

vb写的java编译器将abc.java编译成abc.class用了0.020秒

c++写的java编译器将abc.java编译成abc.class用了0.001秒

delphi写的java编译器将abc.java编译成abc.class用了0.002秒

perl写的java编译器将abc.java编译成abc.class用了0.040秒

最后编译出来的abc.class完全一样,那么这4个编译出来的abc.class在同一个虚拟机上运行时的性能完全一样,难道这可以证明vb,c++,delphi,perl的性能完全一样吗?

再举个例子,有4种java虚拟机(jvm)。一种是用vb写成的,一种是用c++写成的,一种是用delphi写成的,一种是用perl写成的。他们都去运行abc.class的java文件。实际运行过程是这样的:jvm先把abc.class编译成abc.exe(其实只是内存中的二进制指令序列,没有这个文件,为了便于理解,我给出名 abc.exe),然后cpu运行abc.exe。由于四种jvm(vbjvm、cppjvm,delphijvm、perljvm)编译出来的 abc.exe完全一样,所以四种jvm在运行 abc.exe时的性能完全一样,差距只在于:4种jvm将abc.class编译成abc.exe所有的“编译所花费的时间”不同。

cppjvm将abc.class编译成abc.exe花0.001秒, 然后abc.exe运行花费300秒,共300.001秒

vbjvm将abc.class编译成abc.exe花0.010秒, 然后abc.exe运行花费300秒,共300.010秒

delphijvm将abc.class编译成abc.exe花0.002秒, 然后abc.exe运行花费300秒,共300.002秒

perljvm将abc.class编译成abc.exe花0.020秒, 然后abc.exe运行花费300秒,共300.020秒

大家可以看到,虽然vbjvm编译abc.class的速度只是cppjvm的十分之一,但abc.class在vbjvm和在cppjvm上运行所花的时间几乎完全一样,难道这样能证明vb和c++性能一样?当然不能!也就是说,java程序运行所花费的时间,与jvm是用什么写成的几乎没有关系!哪怕这个jvm是用最快的语言写的,将abc.class编译成abc.exe只用了0.001秒,最终也几乎不会影响abc.class在这个jvm上运行的时间。

最终得出结论,java的速度与jvm是用什么语言写成的几乎没有关系。

而java的本地代码是用java的jit和hotspot编译器在程序运行时编译出来的,根本不是c++编译器编译出来的,所以java程序根本不是一个c++程序!

jit和hotspot编译器可以根据程序运行时的profile对本地代码进行inline等优化,c++编译器可以吗?

大家可以去jre1.5.0的安装路径中去看看:

其中的jar文件共有50.5m,由于jar文件是压缩文件,并且bytecode的代码要比native code精简的多(前面已经说过了:一个构造方法在bytecode中只要一个指令,构造方法在c++的编译器却要11个指令。java一个method call只要一个machine子code,但用x86相对需要4个),所以这50.5m的java程序完成的工作大约相当于200m以上的本地代码完成的工作。

而其中的.exe和.dll共有7.7m,本地代码在java运行环境中占的比例连5%都不到。

而这仅有的5%的“c++编译器产生的本地代码”(比如awt.dll)在java程序运行时还要被jit和hotspot编译器重新编译成新的指令序列(例如:符合sse2的指令集的指令),并根据运行时的profile来内联到其它java编译器编译出来的native code中成为全新的nativecode序列。

所以c++编译器编译出来java本地库的机器代码序列在java运行的时候根本看不到,这些机器代码也被java的jit和hotspot编译器重新编译并更改执行序列,这些“c++编译器编译出来的机器代码”已经变成了“java编译器编译出来的机器代码”。最终,在cpu中执行的所有机器语言序列全部是由java编译器产生的,与c++编译器没有一点关系。

c++的速度是由c++编译器在程序员开发时编译出来的机器语言的优化程度决定的。

java的速度是由java的jit和hotspot编译器将java bytecode在运行时“即时”编译成针对本地cpu的优化的本地代码决定的。

比速度的实际就是在比:看c++编译器和java编译器谁能产生更优化的机器代码。

很明显,c++的编译器不如java的jit和hotspot编译器,因为jit和hotspot编译器能针对cpu指令集进行人优化、能在运行时根据使用频率对method进行内联和优化。而c++的静态编译器永远也做不到这些。

两者有着本质的不同,但是有些人用一辈子也无法理解这其中的差别,他们只能抱着一个可怜的、没有任何根据“c++比java快”终其一生。

扫描关注微信公众号