[讨论] 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了
Global site tag (gtag.js) - Google Analytics