当前位置:编程学习 > JAVA >>

如何调制JVM参数

     对于JVM参数调优,对于好多程序员来说都是很头痛的疑问,可能设置的不好,JVM不断执行Full GC,用导致整个系统变得很慢,网站停滞时间能达10秒以上,这种情况可能没隔几分钟就来一次,个人都受不了。

     这种停滞在测试的时候看不出来,只有网站pv达到数十万/天的时候疑问就暴露出来了,要想配置好JVM参数,就得对年轻代、年老代、救助空间和永久代有必须明白,还要明白JVM内存管理逻辑,最后还要根据个人的应用来做控制。对于JVM参数上网一搜就能搜出一大把,也有好多提供实践的例子,我也按照各种例子测试过,最后或者会出现疑问,通过几个月的实践改善,我就网站(需要没有停滞时间)的jvm参数调优给出下面几条经验。

   1:建议用64位操作系统,Linux下64位的JDK比32位JDK要慢多数,但是吃得内存很多,吞吐量更大。

   2:XMX和XMS设置一样大,MaxPermSize和MinPermSize设置一样大,这种可以减轻伸缩堆大小带着的压力。

   3:调试的时候设置多数打印参数,如-XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log,这种可以根据gc.log里看出多数端倪出来。

   4:系统停顿的时候可能是GC的疑问也可能是程序的疑问,多用Jmap和Jstack查看,或者killall -3 Java,接下来查看Java控制台日志,能看出好多疑问。有一次,网站突然很慢,Jstack一看,原来是个人写的URL Connection连接太多没有释放,改一下程序就OK了。

   5:仔细明白个人的应用,可能用了缓存,当年老代应该大多数,缓存的HashMap不应该没有限制长,建议采取LRU算法的Map做缓存,LRUMap的最大长度也要根据实际情况设定。

   6:没有用的回收时Promotion Failed是个很头痛的疑问,那么可能是两种原因产生,第一个原因是救助空间不够,救助空间里的对象还不应该被移动到年老代,但年轻代又有好多对象就得放入救助空间;第二个原因是年老代没有足够的空间接纳来自年轻代的对象;这两种情况都会转向Full GC,网站停顿时间较长。第一个原因我的最后处理做法是去掉救助空间,设置-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0就好,第二个原因我的处理做法是设置CMSInitiatingOccupancyFraction为某个值(假设70),这种年老代空间到70%时就开始执行CMS,年老代有足够的空间接纳来自年轻代的对象。

   7:不管怎样,永久代或者会逐渐变满,所以隔三差五重起Java服务器是需要的,我每天都自动重起。

   8:采取并发回收时,年轻代小一点,年老代要大,因为年老大用的是并发回收,即使时间长点也不会影响别的程序继续运行,网站不会停顿,我的最后配置如下(系统8G内存),每天几百万PV一点疑问都没有,网站没有停顿,2009年网站没有因为内存疑问down过机。

  1.  
  2. $JAVA_ARGS .= " -Dresin.home=$SERVER_ROOT -server -Xms6000M -Xmx6000M -Xmn500M -XX:PermSize=500M   
  3.  
  4. -XX:MaxPermSize=500M -XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0 -Xnoclassgc -XX:+DisableExplicitGC   
  5.  
  6. -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection   
  7.  
  8. -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:-CMSParallelRemarkEnabled   
  9.  
  10. -XX:CMSInitiatingOccupancyFraction=90 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram   
  11.  
  12. -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log ";  
  13.  

   说明一下,-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0可以去掉了救助空间:

   ◆-Xnoclassgc禁用类没有用的回收,能力会高一点;
   ◆-XX:+DisableExplicitGC禁止System.gc(),免得程序员误调用gc做法影响能力;
   ◆-XX:+UseParNewGC,对年轻代采取多线程并行回收,这种收得快;带CMS参数的都是和并发回收相关的。

   CMSInitiatingOccupancyFraction

    这种参数设置有很大技巧,基本上满足(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100>=Xmn就不会出现promotion failed。在我的应用中Xmx是6000,Xmn是500,当Xmx-Xmn是5500兆,也可以年老代有5500兆,CMSInitiatingOccupancyFraction=90说明年老代到90%满的时候开始执行对年老代的并发没有用的回收(CMS),这时还剩10%的空间是5500*10%=550兆,所以即使Xmn(也可以年轻代共500兆)里所有对象都搬到年老代里,550兆的空间也足够了,所以只要满足上面的公式,就不会出现没有用的回收时的Promotion Failed;

    SoftRefLRUPolicyMSPerMB

   这种参数我认为可能有点用,官方解释是softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap,我觉得没需要等1秒;

    网上别的介绍JVM参数的也比较多,估计其中大面积是没有遇到Promotion Failed,或者访问量太小没有机会遇到,(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100>=Xmn这种公式非常是原创,真遇到Promotion Failed了,还得这么处理。

 

CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,