1. JMX获取内存信息
2. jvm启动参数同时使用-XX:+UseAdaptiveSizePolicy和-XX:+UseConcMarkSweepGC
3. 使用sun jdk(1.6.30以上到1.7的全部版本已经确认有该问题,jdk8修复,其他版本待验证)
应用注意点:
UseAdaptiveSizePolicy,以及MaxGCPauseMillis 都是给Parallel GC(一般server的jvm模式,比如64位windows和linux操作系统,默认采用的GC方式,更多版本可以参考官方文档,也可以通过java -version 查看是不是server模式)用的,不建议用于CMS。
以分析HBase的一次问题(CDH提供的官方版本的jvm配置中,将并行GC,CMS和这些参数放在一起导致了该问题,因为开始没有怀疑到这点,所以反而深入了解了具体原因)为例:
一、异常:
1)程序异常 2013-11-11 14:01:21,159 FATAL org.apache.hadoop.hbase.regionserver.HRegionServer: ABORTING region server SERVER_SERVER: Unhandled exception: committed = 10729504768 should be < max = 10379526144
java.lang.IllegalArgumentException: committed = 10729504768 should be < max = 10379526144
at java.lang.management.MemoryUsage.(MemoryUsage.java:145)
at sun.management.MemoryImpl.getMemoryUsage0(Native Method)
at sun.management.MemoryImpl.getHeapMemoryUsage(MemoryImpl.java:61)
at org.apache.hadoop.hbase.regionserver.HRegionServer.buildServerLoad(HRegionServer.java:932)
at org.apache.hadoop.hbase.regionserver.HRegionServer.tryRegionServerReport(HRegionServer.java:906)
at org.apache.hadoop.hbase.regionserver.HRegionServer.run(HRegionServer.java:770)
at java.lang.Thread.run(Thread.java:662)
2013-11-11 14:01:21,160 FATAL org.apache.hadoop.hbase.regionserver.HRegionServer: RegionServer abort: loaded coprocessors are: []
2) jmap -heap 结果:(集群所有节点上都这样,因此猜想jvm参数配置)
Debugger attached successfully.
Server compiler detected.
JVM version is 20.5-b03
using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 10737418240 (10240.0MB)
NewSize = 2147483648 (2048.0MB)
MaxNewSize = 2147483648 (2048.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 4
PermSize = 21757952 (20.75MB)
MaxPermSize = 134217728 (128.0MB)
Heap Usage:
unknown generation type:
capacity = 0 (0.0MB)
used = 0 (0.0MB)
free = 0 (0.0MB)
NaN% used
unknown generation type:
capacity = 0 (0.0MB)
used = 0 (0.0MB)
free = 0 (0.0MB)
NaN% used
Perm Generation:
capacity = 60878848 (58.05859375MB)
used = 37927152 (36.17015075683594MB)
free = 22951696 (21.888442993164062MB)
62.29939173619054% used
二、结果:在HBase中,导致regionserver设置状态abortRequest,于是HRegionServer.run线程退出,其他线程正常服务(jstack对比看出)。abortRequest状态下,regionserver不对外提供任何数据请求服务,所以无法服务。
三、原因
1)程序异常:确认是jvm的bug,初步确认版本为1.6_u30以上,包括1.7都存在该问题(无法登陆官方bugs.sun.com确认),jdk6.30以下版本还未确认(使用1.6_u25版本后,目前还没有复现问题)。
原因简要分析:(http://blog.csdn.net/axman/article/details/8667351)
在使用cms算法下,如果开启参数UseAdaptiveSizePolicy,则每次minor gc后会重新计算eden,from和to的大小,计算过程依据的是gc过程统计的一些数据,计算后的eden+from+to不会超过Xmx,同时from和to一般是不相等(初始化的时候from和to是相等的)。主要问题在于计算完后,如果eden变大,ContiguousSpacePool里面的max_eden_size并没有被更新,还是最开始时候的值,这样导致jvm在通过call_special调用java.lang.management. MemoryUsage的构造函数的时候会产生exception,产生exception的原因是eden的committed 大于 eden的max_size