文章源地址:http://blog.csdn.net/chenyi8888/article/details/4722410
目前市面上就只有三种主流的JVM:SUN、BEA和IBM。
我对三种主流的JVM的都有过使用,并运用到实际的项目当中,来谈谈使用它们的感受。
首先来谈谈SUN的JVM
这个JVM是大家在开发过程中普遍用的比较多的一个,我的开发过程中也是用它居多,总体感觉一般,没有比较特别的地方。因为一个是其GC回收机制,一个是其本身的BUG问题。先来说下BUG问题,我是在06年底,就采用了JDK1.5的版本来进行项目开发,当时使用的版本是JDK1.5_06。这个版本中的线程1.5就有一个非常严重的BUG,它将导致服务器内存泄漏(关于这个问题,SUN官方网站也有提到。而且也有其他人在其博客上也对这个问题进行详细的描述,在此就不细说了)。当时为了解决这个问题花了一个多礼拜的时间,而后续的JDK几个版本(2个版本还是3个,记得不是很清楚)还没有进行修正,最后只能变相的使用线程1.5的技术了。
早期的JDK1.5的版本在运行时很不稳定。我就碰到服务器经常运行3、4天,就莫名其妙的关掉了(也就是进程杀掉了),当时日志没有任何异常信息,就是在当前目录下生成一个java_error_pid.log形式的文件(pid表示linux下的进程号)。最后就只好升级JDK的版本,然后问题得到了解决,以后服务器也不当机了。
还有就是早期的JDK1.5在兼容性方面也存在问题,如JDK1.4的jar包不能直接运行在JDK1.5上,没有达到向前兼容的目的。
不过这些问题在最终的JDK1.5.0_17上都得到了解决。
关于GC回收,SUN的JVM的GC回收由两个部分组成,一个是频繁GC,一个是Full GC。
为了让SUM的JVM运行在更强劲,需要对其配置复杂的参数设置(可参考本人转载一篇《JVM参数调优》,该文章里的内容我都亲自测试过,能让JVM有一个明显性能提升)。
如何通过GC信息来判断程序是否合理,主要是两种方式:一种是通过工具的形式(如jprofiler等工具),一种就是查看GC的日志(关于如何配置GC日志参数,网上有很多资料)。工具判断非常方便只有那个GC图里没有大起大落就行,就是那根线比较平缓。这里主要是介绍下如何通过GC日志来判断(只是个人的经验之谈,可作为参考)。
关于频繁的GC日志信息如下:
10.719: [GC 46136K->17722K(517056K), 0.3663676 secs]
11.239: [GC 39136K->18586K(517056K), 0.0045660 secs]
关于FULL GC的日志信息如下:
16.276: [Full GC 516871K->3239K(517056K), 0.0547627 secs]
19.173: [Full GC 517056K->4240K(517056K), 1.0565893 secs]
SUN的JVM慢其中有一个原因就是频繁GC和FULL GC运行频率高导致,这样会占用系统很多资源。那么如何判断程序运行是否健康呢?
对于频繁GC而言
第一:判断回收量,就是回收前减去回收后的值就是回收量,一般对于单核而言(至少2GB内存)这个回收量保持在8MB至25MB之间比较正常。对于多核而言(我只测试过8核的,4GB内存)回收量保持在20MB至50MB之间比较正常。
第二:判断回收一次的时间。这里是以小数点为标准,一般不管是单核还是多核,小数点右边至少出现2个0,算是比较正常的(如频繁GC信息第二行内容,如果出现第一行的内容,说明程序运行有点问题),而小数点左边一般都是0(如果不是0,只能说明程序有严重的问题)。
对于FULL GC而言
第一:还是判断回收量,不同的是回收量的数字会加大很多而且也和你的JVM最大内存数有关(这里假设最大内存数为512MB),单核(至少2GB内存)一次FULL GC将要回收200MB至350MB算比较正常。多核(8核,4GB内存)下回收量也差不多。第二:还是回收一次的时间,单核下一次FULL GC最好控制在1秒到3秒之间。多核下一次FULL GC最好控制在0秒到1.5秒之间。
再次提醒这些数据只是个参考思路,可能机器配置更强劲,处理的速度会更快吧。还有就是导致程序内存泄露有很多情况,处理的方式也很复杂。到时候我会专门讲一下关于java程序如何避免内存泄露。
那如何提高编写程序的效率呢?其实答案很简单,就是减少FULL GC的次数,如40多分钟一次FULL GC,更好的话就是加大频繁GC一次的回收量。如果是计算机专业的人应该还知道,想提高效率的其他方式就是必须学好数据结构、算法分析和编译原理(这是一个漫长的过程,需要大量的时间进行实践,才能有更深刻的感受)。
接着再谈谈BEA的JVM
它的JVM算是三种当中比较有特点的JVM,性能最强。而且它对线程和网络都做了大量的优化和技巧的工作。我曾经在同一个服务器上使用了SUN和BEA的JVM,分别在单核上进行了的测试(2GB内存),发现BEA的JVM处理量是SUN的JVM的一倍多,在相同的时间内(15天的时间),前者是300百多万的处理量,而后者只有150百万的处理量。
说下它的GC机制,它跟SUN的GC机制有很大不同,其中之一就是没有FULL GC和频繁GC的概念,而且每次GC操作间隔时间较长,回收量也是大小不等,从一次回收几十MB,到有时候一次回收上百MB。其二是使用BEA的JVM启动速度较快。其三参数的设置相对于SUN的设置来说,算是比较简单的(大家可以到网上搜索这方面的资料)。
最后来谈谈IBM的JVM
对于它的JVM实在一次偶然的机会,公司为客户做一个项目时,客户所使用的是IBM整套的解决方案,自然也就使用IBM的自己的JVM了。当时在开发过程中,有点想当然,认为反正java跨平台,所以就没有基于一个IBM的平台上做开发,项目提交后,客户那边也运行很正常没有出现什么大的毛病,过了几天,对方的工程师就打电话过来告诉我们日志信息里有大量的错误信息。要求我们查明,最好花了两天时间检查下来发现,目前IBM的JVM并不支持JDK1.5后的新特性(这里是不支持java NIO里的相关技术),所以只好重新修改代码才把问题解决。
总结说明下:
对于一般的应用而言,建议采用SUN的JVM就足够了;对于对性能要求很高的应用而言,建议采用BEA的JVM,如java版的游戏服务器;对于有钱的公司而言,建议采用IBM的JVM,那是一整套解决方案,后期维护方便(只是开发过程中要注意兼容性的问题,听说IBM的JVM现在更新很慢,所以不一定符合新的java标准)。