Java使用G1垃圾回收器时出现的本地内存泄漏问题及大内存处理方案

4
我们目前存在Java本地内存泄漏问题。服务器很大(40个CPU,128GB内存)。Java堆大小为64G,我们运行一个非常消耗内存的应用程序,将大量数据读入字符串,并使用约400个线程在几分钟后将其从内存中丢弃。
因此,堆栈非常快速地填充,但堆栈上的内容很快就会过时并可以被GCed清除。因此,我们必须使用G1以避免数分钟的STW中断。
现在,这似乎工作得很好 - 堆栈足够大,可以运行应用程序数天,没有任何泄漏。无论如何,Java进程随着时间的推移不断增长,直到使用所有128G,并且应用程序由于分配失败而崩溃。
我已经阅读了很多关于本地Java内存泄漏的资料,包括与最大竞技场(我们使用带有glibc 2.13的wheezy,因此如果不进行分发升级,则无法通过设置MALLOC_ARENA_MAX = 1或4来解决glibc问题)的glibc问题。
因此,我们尝试使用jemalloc,这为我们提供了以下图形: inuse-space: inuse-spaceinuse-objects: inuse-objects
我不明白问题出在哪里,有人有想法吗?
如果我将MALLOC_CONF="narenas:1"设置为tomcat进程运行我们的应用程序的环境参数,那么它是否仍然会以某种方式使用glibc malloc版本?
这是我们的G1设置,可能存在一些问题?
-XX:+UseCompressedOops
-XX:+UseNUMA
-XX:NewSize=6000m
-XX:MaxNewSize=6000m
-XX:NewRatio=3
-XX:SurvivorRatio=1
-XX:InitiatingHeapOccupancyPercent=55
-XX:MaxGCPauseMillis=1000
-XX:PermSize=64m
-XX:MaxPermSize=128m
-XX:+PrintCommandLineFlags
-XX:+PrintFlagsFinal
-XX:+PrintGC
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintTenuringDistribution
-XX:-UseAdaptiveSizePolicy
-XX:+UseG1GC
-XX:MaxDirectMemorySize=2g
-Xms65536m
-Xmx65536m

感谢您的帮助!

通过内存视角来分析这个问题会非常困难。我建议使用Dynatrace等工具监控进程,以更好地了解内存分配、GC吞吐量和CPU利用率。 - Armaiti
今天我成功地解决了一个G1本地内存泄漏问题,这个问题只在高负载和频繁使用System.gc()时才会出现。我使用了OS X上的XCode首先查看了本地堆中泄漏的数据,发现有数百万个32字节的mallocs,然后我使用dtrace确定其中绝大部分32字节的mallocs来自于G1。 - Reuben Scratton
1个回答

0

我们从未显式调用过 System.gc(),并同时停止使用 G1,除了 xms 和 xmx 外没有指定任何其他参数。

因此,现在将近全部的 128G 内存都用于堆。Java 进程的内存使用率很高,但是几周来一直保持稳定。我相信这是某种 G1 或至少是常规 GC 的问题。唯一的缺点是高 GC 暂停时间,但是随着堆大小的增加,从最多 90s 减少到约 1-5s,对于我们服务器上进行基准测试来说还算可以接受。

在此之前,我尝试了 -XX:ParallelGcThreads 选项,当将默认值 28(适用于 40 个 CPU)减少到 1 时,它对内存泄漏速度产生了显著影响。在不同实例上使用不同的值,内存图看起来有点像手持扇子...

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接