gpt4 book ai didi

memory - 如何在 JVM 上调试 native 内存中的泄漏?

转载 作者:行者123 更新时间:2023-12-04 15:08:55 28 4
gpt4 key购买 nike

我们有一个在 Mule 上运行的 Java 应用程序。我们将 XMX 值配置为 6144M,但经常看到整体内存使用量不断攀升。前几天在我们主动重新启动它之前它已经接近 20 GB。

Thu Jun 30 03:05:57 CDT 2016
top - 03:05:58 up 149 days, 6:19, 0 users, load average: 0.04, 0.04, 0.00
Tasks: 164 total, 1 running, 163 sleeping, 0 stopped, 0 zombie
Cpu(s): 4.2%us, 1.7%sy, 0.0%ni, 93.9%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 24600552k total, 21654876k used, 2945676k free, 440828k buffers
Swap: 2097144k total, 84256k used, 2012888k free, 1047316k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3840 myuser 20 0 23.9g 18g 53m S 0.0 79.9 375:30.02 java

jps 命令显示:
10671 Jps
3840 MuleContainerBootstrap

jstat 命令显示:
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT
37376.0 36864.0 16160.0 0.0 2022912.0 1941418.4 4194304.0 445432.2 78336.0 66776.7 232 7.044 17 17.403 24.447

启动参数是(敏感位已更改):
3840 MuleContainerBootstrap -Dmule.home=/mule -Dmule.base=/mule -Djava.net.preferIPv4Stack=TRUE -XX:MaxPermSize=256m -Djava.endorsed.dirs=/mule/lib/endorsed -XX:+HeapDumpOnOutOfMemoryError -Dmyapp.lib.path=/datalake/app/ext_lib/ -DTARGET_ENV=prod -Djava.library.path=/opt/mapr/lib -DksPass=mypass -DsecretKey=aeskey -DencryptMode=AES -Dkeystore=/mule/myStore -DkeystoreInstance=JCEKS -Djava.security.auth.login.config=/opt/mapr/conf/mapr.login.conf -Dmule.mmc.bind.port=1521 -Xms6144m -Xmx6144m -Djava.library.path=%LD_LIBRARY_PATH%:/mule/lib/boot -Dwrapper.key=a_guid -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.disable_console_input=TRUE -Dwrapper.pid=10744 -Dwrapper.version=3.5.19-st -Dwrapper.native_library=wrapper -Dwrapper.arch=x86 -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 -Dwrapper.lang.domain=wrapper -Dwrapper.lang.folder=../lang

将 jps 中的“容量”项相加表明只有我的 6144m 用于 Java 堆。剩下的内存到底在哪里被使用?堆栈内存?原生堆?我什至不确定如何继续。

如果任其继续增长,它将消耗系统上的所有内存,我们最终会看到系统卡住并引发交换空间错误。

我有另一个开始成长的过程。目前大约 11g 常驻内存。
pmap 10746 > pmap_10746.txt
cat pmap_10746.txt | grep anon | cut -c18-25 | sort -h | uniq -c | sort -rn | less

Top 10 entries by count:
119 12K
112 1016K
56 4K
38 131072K
20 65532K
15 131068K
14 65536K
10 132K
8 65404K
7 128K


Top 10 entries by allocation size:
1 6291456K
1 205816K
1 155648K
38 131072K
15 131068K
1 108772K
1 71680K
14 65536K
20 65532K
1 65512K

And top 10 by total size:
Count Size Aggregate
1 6291456K 6291456K
38 131072K 4980736K
15 131068K 1966020K
20 65532K 1310640K
14 65536K 917504K
8 65404K 523232K
1 205816K 205816K
1 155648K 155648K
112 1016K 113792K

这似乎在告诉我,因为 Xmx 和 Xms 设置为相同的值,所以 Java 堆只分配了 6291456K。其他分配不是 java 堆内存。这些是什么?它们被分配到相当大的块中。

最佳答案

扩展彼得的答案的更多细节。

您可以从 VisualVM 中获取二进制堆转储(右键单击左侧列表中的进程,然后单击堆转储 - 不久之后它将出现在下方)。如果您无法将 VisualVM 附加到您的 JVM,您还可以使用以下命令生成转储:

jmap -dump:format=b,file=heap.hprof $PID

然后复制文件并使用 Visual VM 打开它(文件,加载,选择类型堆转储,找到文件。)

正如 Peter 指出的那样,泄漏的一个可能原因可能是未收集的 DirectByteBuffers(例如:另一个类的某些实例没有正确地取消引用缓冲区,因此它们永远不会被 GC)。

要确定这些引用来自何处,您可以使用 Visual VM 检查堆并在“类”选项卡中查找 DirectByteByffer 的所有实例。找到 DBB 类,右击,进入实例 View 。

这将为您提供实例列表。你可以点击一个,看看谁在保留每个人的引用:

Visual VM - Instances view

请注意底部 Pane ,我们有类型为 Cleaner 的“referent”和 2 个“mybuffer”。这些将是引用我们深入研究的 DirectByteBuffer 实例的其他类中的属性(如果您忽略 Cleaner 并专注于其他类应该没问题)。

从现在开始,您需要根据您的应用程序进行操作。

另一种获取 DBB 实例列表的等效方法是从 OQL 选项卡。这个查询:
select x from java.nio.DirectByteBuffer x

为我们提供了与以前相同的列表。使用OQL的好处是可以执行更多 more complex queries .例如,这将获取所有保持对 DirectByteBuffer 的引用的实例:
select referrers(x) from java.nio.DirectByteBuffer x

关于memory - 如何在 JVM 上调试 native 内存中的泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38153381/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com