jdk6不同小版本Garbage collection性能差异问题

其实很早注意到这个现象,但是一直没考虑到jdk本身的问题。相同的java代码跑出了不一样的速度,因为是两个不同的机器,想当然的归结为机器的性能差异。但是仔细研究过后,确认是oracle JDK本身的问题了。
下面是实验数据:

容器使用resin,jvm参数

	<jvm-arg>-Xmx2548m</jvm-arg>
	<jvm-arg>-Xms2548m</jvm-arg>
	<jvm-arg>-Xmn512M</jvm-arg>
	<jvm-arg>-Xss512K</jvm-arg>
	<jvm-arg>-XX:PermSize=128M</jvm-arg>
	<jvm-arg>-XX:MaxPermSize=128M</jvm-arg>
	<jvm-arg>-XX:SurvivorRatio=8</jvm-arg>
	<jvm-arg>-XX:+UseParNewGC</jvm-arg>
	<jvm-arg>-XX:+UseConcMarkSweepGC</jvm-arg>
	<jvm-arg>-XX:+CMSPermGenSweepingEnabled</jvm-arg>
	<jvm-arg>-XX:+CMSClassUnloadingEnabled</jvm-arg>
	<jvm-arg>-XX:+UseCMSCompactAtFullCollection</jvm-arg>
	<jvm-arg>-XX:CMSFullGCsBeforeCompaction=0</jvm-arg>
	<jvm-arg>-XX:+CMSParallelRemarkEnabled</jvm-arg>
	<jvm-arg>-XX:+DisableExplicitGC</jvm-arg>
	<jvm-arg>-XX:+UseCMSInitiatingOccupancyOnly</jvm-arg>
	<jvm-arg>-XX:CMSInitiatingOccupancyFraction=75</jvm-arg>
	<jvm-arg>-XX:SoftRefLRUPolicyMSPerMB=0</jvm-arg>

老版本jdk,是杀掉java进程后重启的:完全无法回收,一直在做fullGC

[root@localhost /usr/local/java/bin]$ ./jstat -gccause 25515 1000
  S0     S1      E      O      P       YGC   YGCT     FGC    FGCT     GCT    LGCC               GCC                 
  0.00  70.25  58.30  86.46  23.91     81   12.692    10    0.498   13.190 CMS Final Remark     No GC               
 39.81  70.25 100.00  84.21  23.91     82   12.692    10    0.498   13.190 unknown GCCause      Allocation Failure  
  0.00  76.34  66.34  83.26  23.91     83   12.841    10    0.498   13.339 unknown GCCause      No GC               
  0.00  85.84   9.98  84.12  23.91     85   13.046    11    0.548   13.594 unknown GCCause      No GC               
 68.63   0.00  64.33  84.99  23.91     86   13.165    11    0.548   13.713 unknown GCCause      No GC               
  0.00  58.93  56.29  85.82  23.91     87   13.260    11    0.548   13.808 unknown GCCause      No GC               
 68.76   0.00  73.34  85.82  23.91     88   13.327    11    0.548   13.875 unknown GCCause      No GC               
  0.00  47.74  10.05  86.26  23.91     89   13.374    11    0.548   13.922 unknown GCCause      No GC               
 42.41   0.00  65.30  85.37  23.91     90   13.420    12    0.686   14.106 unknown GCCause      No GC               
  0.00  61.64  90.46  82.97  23.91     91   13.490    12    0.686   14.176 unknown GCCause      No GC               
 42.80  62.41   0.00  78.90  23.91     93   13.580    13    0.686   14.266 No GC                CMS Initial Mark    
  0.00  62.41  46.48  78.90  24.09     93   13.580    13    0.734   14.314 CMS Initial Mark     No GC

更新JDK后同样杀掉java进程重启:可以正常回收内存

  S0     S1      E       O      P       YGC     YGCT   FGC    FGCT     GCT    LGCC                 GCC        
  16.49   0.00  99.17  74.75  28.26    104   13.303     4    0.753   14.056 unknown GCCause      No GC               
  0.00  13.23   5.91  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  16.86  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  24.91  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  35.45  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  38.63  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  43.78  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  48.12  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  53.89  75.05  28.26    105   13.328     5    0.756   14.085 CMS Initial Mark     No GC               
  0.00  13.23  60.49  74.99  28.26    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  0.00  13.23  64.81  74.42  28.26    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  0.00  13.23  69.19  69.29  28.26    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  0.00  13.23  74.96  68.19  28.14    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  0.00  13.23  80.66  68.19  28.14    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  0.00  13.23  84.39  68.19  28.14    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  0.00  13.23  89.34  68.19  28.14    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  0.00  13.23  93.12  68.19  28.14    105   13.328     6    1.109   14.438 CMS Final Remark     No GC               
  3.91   0.00   4.59  68.20  28.14    106   13.337     6    1.109   14.446 unknown GCCause      No GC

之前的状况体现在shell脚本调用的定时java上,同样的配置同样的代码,北京机房的总比上海的快四五分钟跑完。更换了上海老版本jdk后,速度一致了。
实验结果证明java version “1.6.0_21″这个和更老的版本,GC回收或者说是内存管理性能较差。更新的版本确认到1.6.0_29没有这个问题,中间的版本没有尝试。
所以线上生产环境如果出现一样的java代码某些机器性能明显差异的话,可以检查下jdk版本,必要的时候需要更新解决。

某些网上的参考资料和oracle的官方release note也证实了这个观点:
http://www.oracle.com/technetwork/java/javase/6u29-relnotes-507960.html?ssSourceSiteId=ocomen
修复内存泄露。Memory leak of java.lang.ref.WeakReference objects。
http://www.oracle.com/technetwork/java/javase/6u18-142093.html
更新java hotspot VM,Garbage collection improvements。
http://618119.com/archives/2009/02/21/136.html
这是个相似案例,只是更老旧版本上的问题。
http://bugs.sun.com/bugdatabase/view_bug site link.do?bug_id=6949855
官方的bug追踪。