论坛首页 Java企业应用论坛

JVM的GC-生命不能承受之重

浏览 56181 次
精华帖 (17) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (9)
作者 正文
   发表时间:2008-11-06  
helloboy9527 写道
liuruncheng 写道
Java有RTS(Real Time System)规范,要做实时系统还是用这个做比较靠谱
我们的认证系统是纯C开发的,8台16CPU、32G内存的机器分两组集群,每台缓存超过10G内存,虽然不会有任何停顿,
但是内存泄漏同样是个梦魇,每年都在查内存泄漏,几乎成了无法避免的任务了


就是因为当初怕内存泄漏这个梦魇,才避开C,选择用JAVA来开发此类系统,简洁轻便,开发也非常快。可惜JVM的GC已经成为生命不能承受之重,唉。


Java RTS已经有成熟的产品,IBM和SUN都有不错的解决方案,你可以试试
0 请登录后投票
   发表时间:2008-11-06  
看看这篇文章可能会有帮助:http://java.sun.com/products/hotspot/whitepaper.html

JVM的GC算法有很多种:Generational Copying Collection,Parallel Young Generation Collector,Mark-Compact Old Object Collector,Mostly Concurrent Mark-Sweep Collector和Parallel Old Generation Collector。你可以选择带有并行算法的收集器,如Mostly Concurrent Mark-Sweep Collector和Parallel Old Generation Collector这样可以减少垃圾回收的等待时间,提高响应性。
0 请登录后投票
   发表时间:2008-11-06  
建议尝试BEA JRockit Real Time,一个实时JVM,现在已经收到Oracle旗下了。(http://www.oracle.com/technology/products/jrockit/jrrt/index.html)

从内部测试结果来看,还是挺不错的。基本思路就是并行GC,从理论上来说,不会再出现full GC的现象。
0 请登录后投票
   发表时间:2008-11-06   最后修改:2008-11-06
调整gc参数显然治标不治本,治本的方法前面的大侠们已经说了。
我提供一下我的jvm参数,仅供参考。我的服务器是8G内存,两个四核cpu,PE2950,64位系统
两个JVM,每个JVM的参数如下:
-server -Xms2048m -Xmx2048m -Xmn768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Djava.awt.headless=true -XX:+DisableExplicitGC
这个参数的效果对我的应用比较好
0 请登录后投票
   发表时间:2008-11-06  
CostaR 写道
调整gc参数显然治标不治本,治本的方法前面的大侠们已经说了。
我提供一下我的jvm参数,仅供参考。我的服务器是8G内存,两个四核cpu,PE2950,64位系统
两个JVM,每个JVM的参数如下:
-server -Xms2048m -Xmx2048m -Xmn768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Djava.awt.headless=true -XX:+DisableExplicitGC
这个参数的效果对我的应用比较好


修改下比较好:

-XX:PermSize=128m  建议改成最大128M,避免没有使用。
-XX:ParallelGCThreads=4 改成跟你的CPU CORE 数量一致, 我记得缺省就是CPU的数量, 具体可以查询下MANUAL。
另外, 对于特殊的应用, 比如楼主的应用, 需要你调整你的老生代区域的大小。
确定的方法如下:
   楼主你用命令  jstat -gctuil pid 1000 1000  看几分钟
   看下, 老生代在最小的时候, 一般是FULL GC过后的几秒, 你可以看到老生代区域使用的百分比。 比如是 50%,如果, 老生代一直处于70%的以上的水平, 那么需要把老生代调大, 另外, 我建议你, 把Full GC的收集比例调到, 默认值是70%, 对于你的应用, 我建议你调制到80%。
  然后, 你用jmap看下, 老生代总共占用了多少内存。 一般来说, 你需要把老生代的内存调节到一个合适你的大小。 建议不要超过70%的使用量就可以了。 这样就能腾出大量的内存给新生代。 这个怎么设置你看下资料, 不然, 你无法自己确定作出微小调整。
   这个做法只能尽量避免FULL GC。


这个参数配置方法比较痛苦的是无法使用 jstack, 不知道为什么, 在linux kernal2.4的版本上, 我连接的上, 但是出不了结果。 因为我们是个每天都开发的在线系统, 如果不能看jstack是痛苦的事情, 虽然kill -3 能使用, 但是, 比较郁闷, 老有程序员把输出控制台文件重复使用, 有的系统, 我就看不了控制台输出。
0 请登录后投票
   发表时间:2008-11-06  
3G的cache 问题就在这里了.
不如考虑改小点看看效果.
  • 大小: 306.5 KB
0 请登录后投票
   发表时间:2008-11-07  
EBA Real-time jvm3.0
0 请登录后投票
   发表时间:2008-11-07  
starfeng 写道
helloboy9527 写道
只是最不爽的一个事情就是,为何GC一定要暂停整个应用程序?我宁愿GC可以耗多点CPU,他完整地占着我的一个CPU来做GC也可以,那另外3G个CPU还是可以处理的。我相信如果是用C++来改写这个程序,应该是完全不需要停的。


1) 分开...至少2jvm, cache的做cache, 应用的做应用, 省得相互影响.
2) 分开后, 对cache处理做进一步代码优化(如果还是慢的话). cache方案有很多,opensource产品也多, 不过, 你最好结合你的业务特点, 依据变的程度, 不同jvm处理不同cache.

触发gc的原因是堆不够用, gc过程耗时长的原因是堆过大(另外,对象引用的判断也耗时)
很明显,在你的这个应用中,靠调参去减少堆或增加的堆的大小是没用的.唯一的办法是,分开处理.

业务这一块,堆小一点, gc速度快, 就算经常gc,也没问题.
cache这一块, 堆大一点, 很难很难触发一次gc, 也没问题


这个可能也是个办法,只是觉得不爽而已。为了迁就JVM的弱点,要将业务这样设计。为何JVM自身不能处理大容量的cache,还要用其他如memcached之类的东西?我觉得JVM还有很大的改进空间。期待在JDK7.0中给我惊喜。
0 请登录后投票
   发表时间:2008-11-07  
改变java程序员对gc的完全依赖才是釜底抽薪的办法。
0 请登录后投票
   发表时间:2008-11-07  
sdh5724 写道
CostaR 写道
调整gc参数显然治标不治本,治本的方法前面的大侠们已经说了。
我提供一下我的jvm参数,仅供参考。我的服务器是8G内存,两个四核cpu,PE2950,64位系统
两个JVM,每个JVM的参数如下:
-server -Xms2048m -Xmx2048m -Xmn768m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Djava.awt.headless=true -XX:+DisableExplicitGC
这个参数的效果对我的应用比较好


修改下比较好:

-XX:PermSize=128m  建议改成最大128M,避免没有使用。
-XX:ParallelGCThreads=4 改成跟你的CPU CORE 数量一致, 我记得缺省就是CPU的数量, 具体可以查询下MANUAL。
另外, 对于特殊的应用, 比如楼主的应用, 需要你调整你的老生代区域的大小。
确定的方法如下:
   楼主你用命令  jstat -gctuil pid 1000 1000  看几分钟
   看下, 老生代在最小的时候, 一般是FULL GC过后的几秒, 你可以看到老生代区域使用的百分比。 比如是 50%,如果, 老生代一直处于70%的以上的水平, 那么需要把老生代调大, 另外, 我建议你, 把Full GC的收集比例调到, 默认值是70%, 对于你的应用, 我建议你调制到80%。
  然后, 你用jmap看下, 老生代总共占用了多少内存。 一般来说, 你需要把老生代的内存调节到一个合适你的大小。 建议不要超过70%的使用量就可以了。 这样就能腾出大量的内存给新生代。 这个怎么设置你看下资料, 不然, 你无法自己确定作出微小调整。
   这个做法只能尽量避免FULL GC。


这个参数配置方法比较痛苦的是无法使用 jstack, 不知道为什么, 在linux kernal2.4的版本上, 我连接的上, 但是出不了结果。 因为我们是个每天都开发的在线系统, 如果不能看jstack是痛苦的事情, 虽然kill -3 能使用, 但是, 比较郁闷, 老有程序员把输出控制台文件重复使用, 有的系统, 我就看不了控制台输出。



将新生代调大,可以使得minor GC的次数会减少,但每次minor GC的时间反而是增得更大了,根据我的经验,如果新生代为1.5G左右,minor GC已经需要用到快0.3秒了。而minor GC同样是stop-the-whole-world,这样客观上还是不解决问题。

我需要的是一种GC算法,可以在多核的情况下,在较大内存(10多G)的情况下,不管是minor GC,或者是Full GC,均不要stop-the-whold-world,或者停顿非常短的时间(0.1秒以下)。他的CPU可以耗多一点,完整耗掉一个CPU也可以。目前查了几天的资料,看来现在是没有的,期待SUN以后给我们惊喜。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics