解决无限制的Java Resident Set Size(RSS)增长问题

时间:2012-07-23 05:19:56

标签: java memory

我有一个独立的Java应用程序,它具有:

-Xmx1024m -Xms1024m -XX:MaxPermSize=256m -XX:PermSize=256m

随着时间的推移,它会占用越来越多的内存,开始交换(并减速)并最终死了很多次(不是OOM +转储,只是死了,没有/ var / log / messages)。 / p>

到目前为止我尝试过:

  1. 堆转储:活动对象占用1G堆中的200-300Mb - >好吧用堆
  2. 活线程数相当恒定(~60-70) - >好的线程堆栈
  3. JMX在某个时刻停止回答(mb它答案但是超时更低)
  4. 关闭交换 - 它死得更快
  5. strace - 似乎一切都慢了下来,应用仍然没有死,并且不确定哪些东西看起来
  6. 检查顶部:VIRT增长到5.5Gb,RSS增加到3.7 Gb
  7. 检查vmstat(显然我们开始交换):

     --------------------------procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
    Sun Jul 22 16:10:26 2012:  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    Sun Jul 22 16:48:41 2012:  0  0 138652 2502504  40360 706592    1    0   169    21 1047  206 20  1 74  4  0
    . . . 
    Sun Jul 22 18:10:59 2012:  0  0 138648  24816  58600 1609212    0    0   124   669  913 24436 43 22 34  2  0
    Sun Jul 22 19:10:22 2012: 33  1 138644  33304   4960 1107480    0    0   100   536  810 19536 44 22 23 10  0
    Sun Jul 22 20:10:28 2012: 54  1 213916  26928   2864 578832    3  360   100   710  639 12702 43 16 30 11  0
    Sun Jul 22 21:10:43 2012:  0  0 629256  26116   2992 467808   84  176   278  1320 1293 24243 50 19 29  3  0
    Sun Jul 22 22:10:55 2012:  4  0 772168  29136   1240 165900  203   94   435  1188 1278 21851 48 16 33  2  0
    Sun Jul 22 23:10:57 2012:  0  1 2429536  26280   1880 169816 6875 6471  7081  6878 2146 8447 18 37  1 45  0
    
  8. sar还显示稳定的系统%增长=交换:

     15:40:02          CPU     %user     %nice   %system   %iowait    %steal     %idle
     17:40:01          all     51.00      0.00      7.81      3.04      0.00     38.15
     19:40:01          all     48.43      0.00     18.89      2.07      0.00     30.60
     20:40:01          all     43.93      0.00     15.84      5.54      0.00     34.70
     21:40:01          all     46.14      0.00     15.44      6.57      0.00     31.85
     22:40:01          all     44.25      0.00     20.94      5.43      0.00     29.39
     23:40:01          all     18.24      0.00     52.13     21.17      0.00      8.46
     12:40:02          all     22.03      0.00     41.70     15.46      0.00     20.81
    
  9. 检查pmap是否有以下最大的贡献者:

      000000005416c000 1505760K rwx--    [ anon ]
      00000000b0000000 1310720K rwx--    [ anon ]
      00002aaab9001000 2079748K rwx--    [ anon ]
    
  10. 尝试关联我从strace转储的pmap中获得的地址给了我没有匹配

  11. 添加更多内存不切实际(稍后会出现问题)

  12. 切换JVM是不可能的(env不受我们控制)
  13. 问题是:     我还可以尝试追踪问题的原因或尝试解决问题吗?

3 个答案:

答案 0 :(得分:1)

JVM中的某些内容正在使用“无限制”的非堆内存。一些可能的候选人是:

  • 线程堆栈。
  • 由某些本机代码库分配的本机堆。
  • 内存映射文件。

当您进行线程堆栈转储时,第一种可能性将显示为大量(且不断增加)的线程数。 (检查一下......好吗?)

如果您的应用程序(或它使用的某些第三方库)不使用任何本机库,您可以(可能)消除第二个。

如果你的应用程序(或它使用的某个第三方库)不使用内存映射文件,你可以消除第三个。


我猜你没有看到OOME的原因是你的JVM被Linux OOM杀手杀死了。 JVM也可能在本机代码中拯救(例如由于malloc故障未得到正确处理),但我认为JVM崩溃转储的可能性更大......

答案 1 :(得分:1)

问题出在附加的探查器库中 - 它记录了CPU调用/分配站点,因此需要内存来存储它。

所以,人为因素在这里:)

答案 2 :(得分:1)

Java和glibc> = 2.10存在已知问题(包括Ubuntu> = 10.04,RHEL> = 6)。

治愈就是设定这个环境。变量: export MALLOC_ARENA_MAX=4

有一篇关于设置MALLOC_ARENA_MAX的IBM文章 https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

This blog post says

  已知驻留记忆以类似于a的方式蠕变   内存泄漏或内存碎片。

在Google或SO上搜索MALLOC_ARENA_MAX以获取更多参考资料。

您可能还想调整其他malloc选项以优化分配内存的低碎片:

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536
相关问题