[讨论] java进程内存泄露的问题
charleehu
2012-01-30
机器配置:8核8G,Linux 2.6.18-238.9.1.el5
JAVA版本: java version "1.6.0_10" Java(TM) SE Runtime Environment (build 1.6.0_10-b33) Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode) JVM参数: -Xms4000M -Xmx4000M -Xss128k -XX:ThreadStackSize=128 -XX:PermSize=64m -XX:MaxPermSize=512m -verbose:gc -XX:+PrintGCDetails -XX:+UseParallelGC -XX:+PrintGCTimeStamps -Djava.library.path=/opt/resin/libexec:/opt/j2sdk/lib:/usr/lib64 -Djmagick.systemclassloader=false -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dresin.home=/opt/resin -Dserver.root=/opt/resin -Djava.util.logging.manager=com.caucho.log.LogManagerImpl -Djavax.management.builder.initial=com.caucho.jmx.MBeanServerBuilderImpl JMAP堆快照: 引用 Attaching to process ID 12940, please wait...
Debugger attached successfully. Server compiler detected. JVM version is 11.0-b15 using thread-local object allocation. Parallel GC with 8 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 4194304000 (4000.0MB) NewSize = 2686976 (2.5625MB) MaxNewSize = -65536 (-0.0625MB) OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 67108864 (64.0MB) MaxPermSize = 536870912 (512.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 1315307520 (1254.375MB) used = 969317312 (924.4130249023438MB) free = 345990208 (329.96197509765625MB) 73.69510911030144% used From Space: capacity = 41025536 (39.125MB) used = 15255704 (14.548973083496094MB) free = 25769832 (24.576026916503906MB) 37.18587369583666% used To Space: capacity = 40370176 (38.5MB) used = 0 (0.0MB) free = 40370176 (38.5MB) 0.0% used PS Old Generation capacity = 2796224512 (2666.6875MB) used = 1080812704 (1030.7433166503906MB) free = 1715411808 (1635.9441833496094MB) 38.65257240116777% used PS Perm Generation capacity = 67108864 (64.0MB) used = 34289328 (32.70085144042969MB) free = 32819536 (31.299148559570312MB) 51.09508037567139% used TOP命令看到JAVA进程目前已经占用了6.7G的物理内存,活动线程540左右,请问这种内存泄露该从哪入手? |
|
gogole_09
2012-01-30
看日志结果,
貌似堆内存最大只有4000M,其余的内存是不是用了大量的nio ,导致开辟了本地内存? |
|
charleehu
2012-01-30
gogole_09 写道 看日志结果,
貌似堆内存最大只有4000M,其余的内存是不是用了大量的nio ,导致开辟了本地内存? 请问你是指ByteBuffer的allocateDirect么。。。项目中代码没用过这个。难道是第三方lib么。。。 |
|
RednaxelaFX
2012-01-30
试试看你能不能用这个工具看看NIO direct memory用了多少:https://gist.github.com/1593521
|
|
charleehu
2012-01-30
RednaxelaFX 写道 试试看你能不能用这个工具看看NIO direct memory用了多少:https://gist.github.com/1593521
引用 [root@NYSJHL102-239 ~]# /opt/j2sdk/bin/java -cp /opt/j2sdk/lib/sa-jdi.jar:. DirectMemorySize `pgrep java`
这个应该是正常的吧?
Attaching to process ID 12940, please wait... Debugger attached successfully. Server compiler detected. JVM version is 11.0-b15 NIO direct memory: reserved size = 11.118781MB (11658887 bytes) max size = 3833.375000MB (4019585024 bytes) |
|
RednaxelaFX
2012-01-30
charleehu 写道 引用 [root@NYSJHL102-239 ~]# /opt/j2sdk/bin/java -cp /opt/j2sdk/lib/sa-jdi.jar:. DirectMemorySize `pgrep java`
Attaching to process ID 12940, please wait... Debugger attached successfully. Server compiler detected. JVM version is 11.0-b15 NIO direct memory: reserved size = 11.118781MB (11658887 bytes) max size = 3833.375000MB (4019585024 bytes) 我写的这个工具显示的reserved size就是NIO direct memory当前所分配的内存大小。只有11M的话不算多…于是排除NIO内存泄漏的问题。 或许真的有啥JVM外的内存泄漏了。但说真的我也没啥好办法。这方面还有待学习 ![]() 挂上perftools或许能帮助分析,或许没用。如果有用到java.util.zip.Inflater/Deflater,显式调用它们的close()或许有帮助。 =============================== 下面是不靠谱的乱弹: 如果仍然怀疑内存占用量大跟JVM相关,那看看Java线程数有多少,分析jstack的输出可以得到这个信息,然后乘上-Xss会得到有多少空间被分配给线程的栈了。如果说每个栈128K,总共540左右个Java线程,那也才60来M而已,没多少。 然后看看PermGen的最大大小。这里已经用MaxPermSize参数设过了所以很容易看到,也没多少。正常使用的时候能使用的PermGen大小肯定不会超过MaxPermSize,所以肯定没关系。 然后jinfo -flag ReservedCodeCacheSize <pid>可以看到最多有多少空间可以被分配给code cache用;这是用来存HotSpot VM动态生成的代码的地方,包括解释器、stub、动态编译出来的代码都存在这里。这不是PermGen的一部分。这里没调过参数的话大概是50M左右,也没多少。 VM其它一些长时间存活的数据结构也不大。HotSpot VM里有些bug,例如说server compiler里的bug,可能会在native memory里瞬间分配非常大的数组,如果当时无法分配出那么大的空间那VM直接就crash了。如果能分配出来就没事了,这些数据结构很快就会被释放掉。 总之我想说的是JVM自己不是没有内存泄漏,但这种bug非常少。如果你真的怀疑是JVM的bug,那可以试试升级JDK到最新的版本。如果你看到Java heap里状况正常,但从top里看到RSS的值很高,那多半是你用的native library出了问题。 |
|
charleehu
2012-01-30
RednaxelaFX 写道 charleehu 写道 引用 [root@NYSJHL102-239 ~]# /opt/j2sdk/bin/java -cp /opt/j2sdk/lib/sa-jdi.jar:. DirectMemorySize `pgrep java`
Attaching to process ID 12940, please wait... Debugger attached successfully. Server compiler detected. JVM version is 11.0-b15 NIO direct memory: reserved size = 11.118781MB (11658887 bytes) max size = 3833.375000MB (4019585024 bytes) 我写的这个工具显示的reserved size就是NIO direct memory当前所分配的内存大小。只有11M的话不算多…于是排除NIO内存泄漏的问题。 或许真的有啥JVM外的内存泄漏了。但说真的我也没啥好办法。这方面还有待学习 ![]() 挂上perftools或许能帮助分析,或许没用。如果有用到java.util.zip.Inflater/Deflater,显式调用它们的close()或许有帮助。 =============================== 下面是不靠谱的乱弹: 如果仍然怀疑内存占用量大跟JVM相关,那看看Java线程数有多少,分析jstack的输出可以得到这个信息,然后乘上-Xss会得到有多少空间被分配给线程的栈了。如果说每个栈128K,总共540左右个Java线程,那也才60来M而已,没多少。 然后看看PermGen的最大大小。这里已经用MaxPermSize参数设过了所以很容易看到,也没多少。正常使用的时候能使用的PermGen大小肯定不会超过MaxPermSize,所以肯定没关系。 然后jinfo -flag ReservedCodeCacheSize <pid>可以看到最多有多少空间可以被分配给code cache用;这是用来存HotSpot VM动态生成的代码的地方,包括解释器、stub、动态编译出来的代码都存在这里。这不是PermGen的一部分。这里没调过参数的话大概是50M左右,也没多少。 VM其它一些长时间存活的数据结构也不大。HotSpot VM里有些bug,例如说server compiler里的bug,可能会在native memory里瞬间分配非常大的数组,如果当时无法分配出那么大的空间那VM直接就crash了。如果能分配出来就没事了,这些数据结构很快就会被释放掉。 总之我想说的是JVM自己不是没有内存泄漏,但这种bug非常少。如果你真的怀疑是JVM的bug,那可以试试升级JDK到最新的版本。如果你看到Java heap里状况正常,但从top里看到RSS的值很高,那多半是你用的native library出了问题。 谢谢R大的耐心回复 ![]() ![]() jconsole里显示各种正常,一开始用的CMS,换成Parallel还是这样。。。正如你说的看来应该是JVM外的内存泄漏了。这会已经上6.8了,在吃SWAP了 ![]() |