一、现象
以完全相同的启动脚本(除了堆内存JVM参数之外,其他JVM参数未指定)运行完全相同的应用程序分别在A和B服务器上,A上JDK环境是OpenJDK 1.7,B上JDK环境是Oracle JDK 1.6,两应用程序的请求量也几乎相同,系统资源也可确保不是瓶颈所在。
通过JVM进程监控系统发现:A上的应用程序YGC次数多时间长。
二、诊断与解决
YGC跟年轻代相关,通过jstat -gccapacity JVM进程ID
命令分别查看A和B上应用程序的相关容量值。
结果如下:
1 | A上应用程序: |
1 | B上应用程序: |
可发现:A上年轻代容量(1107520
)小于B上年轻代容量(1398080
),最主要的是A上“Eden/Survivor”比值(886080/110720
约等于8)大大小于B上该比值(1265920/65152
约等于19)。
A上“Eden/Survivor”比值接近于“SurvivorRatio”这个JVM参数的默认值,应该是由该JVM参数控制;B上“Eden/Survivor”比值应该不是由该JVM参数控制,而应该是经过动态调整得到的,故而可以定位到“UseAdaptiveSizePolicy”JVM参数。
通过jinfo -flag UseAdaptiveSizePolicy JVM进程ID
命令,可发现A上如预期果然未开启“UseAdaptiveSizePolicy”JVM参数,B上如预期默认开启了“UseAdaptiveSizePolicy”JVM参数,这个差异很明显是不同JDK环境造成的。
因此,具体解决方案有两个:
- 统一JDK环境,将A上的OpenJDK 1.7改为Oracle JDK 1.6
- A上应用程序手动开启“UseAdaptiveSizePolicy”JVM参数