一同事为中间件处理内存泄漏有关问题的解决方案(调整JVM参数)
一同事为中间件处理内存泄漏问题的解决方案(调整JVM参数)
author: li guangju @ HT
今天外汇交易中心的out of memory error的问题基本解决,截止到下班为止,测试环境系统运行稳定,没有出现问题。
(1).这两天观察到的问题主要是JVM配置不当的问题,已基本解决。
在处理JVM配置之前,测试环境初始的JVM配置参数为:
-Xms768m -Xmx768m
JVM某一时刻的heap情况如下(其他时刻也跟此基本一致):
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 805306368 (768.0MB)
NewSize = 2686976 (2.5625MB)
MaxNewSize = -65536 (-0.0625MB)
OldSize = 1835008 (1.75MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 21757952 (20.75MB)
MaxPermSize = 88080384 (84.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 241631232 (230.4375MB)
used = 92984096 (88.67654418945312MB)
free = 148647136 (141.76095581054688MB)
38.48182009848793% used
Eden Space:
capacity = 214827008 (204.875MB)
used = 92607000 (88.3169174194336MB)
free = 122220008 (116.5580825805664MB)
43.10770831943067% used
From Space:
capacity = 26804224 (25.5625MB)
used = 377096 (0.35962677001953125MB)
free = 26427128 (25.20287322998047MB)
1.406852890051956% used
To Space:
capacity = 26804224 (25.5625MB)
used = 0 (0.0MB)
free = 26804224 (25.5625MB)
0.0% used
tenured generation:
capacity = 536870912 (512.0MB)
used = 31052128 (29.613616943359375MB)
free = 505818784 (482.3863830566406MB)
5.783909559249878% used
Perm Generation:
capacity = 27787264 (26.5MB)
used = 27771432 (26.484901428222656MB)
free = 15832 (0.01509857177734375MB)
99.94302425744398% used
从上面可以看出,JVM的NewSize 、MaxNewSize、OldSize、PermSize 设置太小。PermSize使用率已达到99.9%,这应该是造成OutOfMemoryError错误的主要原因之一。另外,新生代分配较小,当遇到大 的对象分配(从开发处了解到InternalHub2.0相对之前的1.0版本增加了许多大对象的分配),而新生代又不够时,就会直接向老年代申请分配担 保,直接将大对象分配到老年代,而此时老年代也太小,容不下大对象,这时也会造成OutOfMemoryError错误。在测试环境的默认JVM参数情况下,系统一直在多次的进行full GC, 而minor GC基本没有,这也从另一个测面验证了full GC太过频繁。
针对上述情况,对测试环境的JVM进行了重新配置,配置参数如下:
-Xms768m -Xmx768m -Xmn288m -XX:OldSize=30m -XX:PermSize=40m -XX:MaxPermSize=80m -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=4 -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -Xloggc:/home/imix/imixapp/InternalHub2.0/perf_test/log/gc.log -Dcom.sun.management.jmxremote.port=10900 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -agentpath:/home/imix/imixapp/InternalHub2.0/perf_test/jprofiler/jprofiler8/bin/linux-x64/libjprofilerti.so=port=9949,nowait,id=106,config=/home/imix/imixapp/InternalHub2.0/perf_test/jprofiler/jprofiler8/config/config.xml
其中,-Dcom.sun.management.jmxremote.port=10900 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false三个参数作用是为了远程jconsole或 jvisualVM监控所用。建议在测试环境或生产环境中都加上此参数,以方便随时监控系统运行情况(在没打开jconsole或jvisualVM的情 况下,基本不会影响系统性能)。
-agentpath:/home/imix/imixapp/InternalHub2.0/perf_test/jprofiler /jprofiler8/bin/linux-x64 /libjprofilerti.so=port=9949,nowait,id=106,config=/home/imix/imixapp /InternalHub2.0/perf_test/jprofiler/jprofiler8/config/config.xml参数为配置的 jprofiler剖析工具所用。在开发环境或测试环境可以加上此参数,在生产系统中,建议关闭,以免影响性能。
在对测试环境的JVM做如上设置之后,系统某一时刻heap如下:
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 805306368 (768.0MB)
NewSize = 301989888 (288.0MB)
MaxNewSize = 301989888 (288.0MB)
OldSize = 31457280 (30.0MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 41943040 (40.0MB)
MaxPermSize = 83886080 (80.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 271843328 (259.25MB)
used = 127598560 (121.68746948242188MB)
free = 144244768 (137.56253051757812MB)
46.9382717386391% used
Eden Space:
capacity = 241696768 (230.5MB)
used = 125549928 (119.7337417602539MB)
free = 116146840 (110.7662582397461MB)
51.945224190999525% used
From Space:
capacity = 30146560 (28.75MB)
used = 2048632 (1.9537277221679688MB)
free = 28097928 (26.79627227783203MB)
6.795574685801631% used
To Space:
capacity = 30146560 (28.75MB)
used = 0 (0.0MB)
free = 30146560 (28.75MB)
0.0% used
tenured generation:
capacity = 503316480 (480.0MB)
used = 33062704 (31.531051635742188MB)
free = 470253776 (448.4689483642578MB)
6.568969090779622% used
Perm Generation:
capacity = 41943040 (40.0MB)
used = 27670656 (26.3887939453125MB)
free = 14272384 (13.6112060546875MB)
65.97198486328125% used
可以明显看到系统各项指标使用率降了下来。同时,minor GC的次数明显上升,数倍于full GC次数,JVM运行基本回到正常状态。
在今天近一天的测试过程中,我们一直对JVM进行了监控,观察到系统运行一直很稳定,GC回收功能正常,占用的内存也没有明显的增加,没有出现outofmemory error的错误。
下午我们去生产环境看了一下JVM的配置,基本跟测试环境的问题一样,可能也需要对JVM参数进行类似设置,以确保系统运行良好。之前1.0版本在如此配置的生产环境上运行,没有出现outofmemory error的错误,而2.0出现错误,原因应该是1.0跟2.0的差别:2.0新增加了许多大对象的操作,导致在之前配置情况下出错。
(2).至于代码中是否存在内存泄漏,在我测试的这一天时间内,暂时还未发现明显的内存泄漏的迹象。不过,下午我对2.0项目的代码使用findbugs工具进行了扫描,发现了99个可疑的bugs,已报给开发,开发可以对这些bugs进行一一排查。