Java进程的内存无限增长,但MemoryMXBean报告稳定的堆和非堆大小【JAVA教程】

!
也想出现在这里? 联系我们
信息

Java进程的内存无限增长,但MemoryMXBean报告稳定的堆和非堆大小,第1张

概述Java进程内存无限增长,但MemoryMXBean报告稳定的堆和非堆大小

我正在与开发在1GB linux目标系统上运行的Java GUI应用程序的团队合作。

我们有一个问题,我们的java进程使用的内存无限增长,直到linux终于杀死了java进程。

我们的堆内存是健康稳定的。 (我们已经广泛地描述了我们的堆)我们还使用MemoryMXBean来监视应用程序的非堆内存使用情况,因为我们相信问题可能在于此。 但是,我们所看到的是报告的堆大小+报告的非堆大小保持稳定。

下面是一个例子,说明在我们的目标系统上运行1GB RAM(由MemoryMXBean报告的堆和非堆,由使用linux的顶层命令(驻留内存)监控的Java进程使用的总内存)时的数字。

现在是否值得实施一个slab分配器?

为什么连续调用new 不分配连续内存?

分段错误无效内存0x0

Windbg <未分类>内存区域

Python – 在windows中获取进程名称,cpu,内存使用情况和峰值内存使用情况

在启动时:

提交200 MB堆

提交了40 MB非堆

java进程使用的320 MB

1天后:

提交200 MB堆

提交了40 MB非堆

java进程使用360 MB

2天后:

提交200 MB堆

提交了40 MB非堆

java进程使用了​​400 MB

上面的数字只是我们系统如何执行的一个“更清晰”的表示,但它们相当准确,接近现实。 正如你所看到的,趋势是明确的。 运行该应用程序几周后,由于系统内存不足,linux系统开始出现问题。 事情开始放缓。 几个小时后,Java进程被终止。

经过几个月的分析并试图理解这一点,我们仍然处于亏损状态。 我感觉很难find有关这个问题的信息,因为大多数讨论最终都是在解释堆或其他非堆内存池。 (如Metaspace等)

我的问题如下:

如果你把它分解下来,java进程使用的内存是什么? (除了堆和非堆内存池之外)

还有哪些潜在的内存泄漏源? (本地代码?JVM开销?)通常,哪些是最可能的元凶?

如何监视/分析这个内存? 堆外的所有东西+非堆现在对我们来说都是一个黑盒子。

任何帮助将不胜感激。

如何解释内存分配延迟的剧烈跳跃?

JVM内存和cpu使用的实际限制?

虚拟机pipe理程序guest os中的内存地址转换

如何创build作为windows服务运行的Java进程的内存转储?

你如何处理使用36位映射的IO?

我会试着部分回答你的问题。

我试图坚持在这种情况下的基本策略是监视每个可用的内存池,打开的文件,套接字,缓冲池,线程数等的最大/使用/峰值。 可能会漏掉套接字连接/打开的文件/线程,您可能会错过。

在你的情况下,看起来你真的有一个本地内存泄漏的问题,这是相当讨厌,很难找到。

你可能会试图分析内存。 看一下GC根,找出哪些是JNI全局引用。 它可以帮助你找出哪些类别可能不被收集。 例如,这是awt中可能需要显式组件处理的常见问题 。

检查JVM的内部内存使用情况(不属于堆/离堆内存) -XX:NativeMemoryTracking非常方便。 它允许你跟踪线程堆栈的大小,gc /编译器的开销等等。 最重要的是你可以在任何时间点创建一个基线,然后追踪记忆差异

# jcmd <pID> VM.native_memory baseline # jcmd <pID> VM.native_memory summary.diff scale=MB Total: reserved=664624KB -20610KB,committed=254344KB -20610KB …

您还可以使用JMX com.sun.management:type=DiagnosticCommand/vmNativeMemory命令生成此报告。

并且…您可以深入并检查pmap -x <pID>和/或procfs内容。

我们似乎终于找到了我们所遇到的问题的根源。 这是什么具体导致这个问题的答案,因为它不可能用于其他人。

TLDR:

这个问题是由JDK中的一个错误引起的,而这个错误现在已经修复,并且将会与JDK 8u152一起发布。 链接到错误报告

整个故事:

我第一次发布这个问题后,我们继续监视我们的应用程序的内存性能, vsminkov建议的XX:NativeMemoryTracking大大缩小了内存泄漏的范围。

我们发现,“踏面竞技场”面积无限增长。 由于这种泄漏是我们以前没有经历过的事情,所以我们开始使用早期版本的Java进行测试,以确定是否在某个特定时刻引入了这种泄漏。

在回到java 8u73之后,漏洞并不存在,虽然被迫使用一个较老的JDK版本并不是最佳的,但至少我们现在有办法解决这个问题。

几个星期后,在更新73上运行时,我们注意到应用程序仍在泄漏,我们又一次开始寻找一个罪魁祸首。 我们发现问题现在位于Class – malloc区域。

在这一点上,我们几乎可以肯定,泄漏不是我们的应用程序的错误,我们正在考虑联系甲骨文将这个问题报告为一个潜在的错误,但后来我的一个同事偶然发现了JDK热点编译器的这个错误报告: 链接到错误报告

错误描述与我们所看到的非常相似。 根据报告中的内容,自从java 8发布以来,内存泄漏一直存在,经过对JDK 8u152的早期版本的测试之后,我们现在相当肯定泄漏是固定的。 运行5天后,我们的应用程序的内存占用率现在似乎接近100%稳定。 类malloc面积仍然略有增长,但它现在正在以每天约100 KB的速度增长(与之前的几个MB相比),并且只测试了5天,我不能肯定它最终不会稳定。

我不能肯定地说,但似乎有可能我们与Class malloc和Thread arenas增长有关的问题。 无论如何,这两个问题在更新152中都没有了。不幸的是,这个更新似乎并没有计划在2017年底之前正式发布,但是到目前为止,我们对早期版本的测试似乎很有前景。

总结

以上是内存溢出为你收集整理的Java进程的内存无限增长,但MemoryMXBean报告稳定的堆和非堆大小全部内容,希望文章能够帮你解决Java进程的内存无限增长,但MemoryMXBean报告稳定的堆和非堆大小所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

© 版权声明
THE END
喜欢就支持一下吧
点赞133 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容