我的项目已经开始使用java 7中的java 8。
切换到java 8后,我们发现消耗的内存随着时间的推移而越来越高。
以下是我们所做的调查:
现在剩下的唯一途径是分析内存如何在java 7和java 8中进行分发,特别是私有字节内存。这里的任何想法或链接将不胜感激。
注意:这个javaw应用程序是基于swing的应用程序。
UPDATE 1 :使用NMT工具分析本机内存并生成与基线比较时占用的内存差异。我们发现堆保持相同但线程正在泄漏所有这些内存。因此Heap没有变化,我假设这个泄漏是由于本机代码。
所以挑战仍然存在。对 如何分析所有线程占用的内存 的任何想法都会对此有所帮助。 以下是从本机内存跟踪中获取的快照。
在这张图片中,你可以看到88 MB的线程增加了。竞技场和资源处理数量增加了很多。
在这张图片中你可以看到这个Malloc中有73 MB增加了。但是这里没有显示方法名称。
所以请在理解这两个截图时提供一些信息。
答案 0 :(得分:5)
您可以尝试在Java 7和probably the default GC in Java 9中引入的另一个GC实现,如G1。为此,只需使用以下命令启动Java应用程序:
-XX:+UseG1GC
Java 8u20中的G1 GC也是一个有趣的功能,可以在堆中查找重复的字符串,并且重复数据删除"它们(这只适用于激活G1,而不是使用默认的Java 8 GC)。
-XX:+UseStringDeduplication
请注意在进行此类更改之前彻底测试您的系统!!!
Here you can find a nice description of the diferent GCs you can use
答案 1 :(得分:2)
考虑优化JVM选项
答案 2 :(得分:2)
在这个my answer中,您可以看到有关如何分析JVM的本机内存以查找内存泄漏的信息和参考。不久,请参阅this。
<强>更新强>
您使用 -XX:NativeMemoryTracking = detail 选项吗?结果很简单,它们表明malloc分配的内存最多。 :)这有点明显。下一步是分析您的应用程序。要分析本机方法和Java,我使用perf_events(我们在生产中使用)火焰图。看看这个blog post是一个好的开始。
请注意,线程的内存增加,可能是您的线程在应用程序中增长。在perf之前,我建议在之前/之后分析线程转储以检查Java线程数是否增长以及原因。您可以使用jstack / jvisualvm / jmc等获得的线程转储
答案 3 :(得分:2)
我遇到了完全相同的问题。
堆使用常量,只有元空间增加,NMT差异显示在特定于竞技场分配中的线程使用的内存中缓慢但稳定的泄漏。我试图通过设置MALLOC_ARENAS_MAX = 1 env var来修复它,但这并不富有成效。使用jemalloc / jeprof分析本机内存分配显示没有泄漏可归因于客户端代码,而是指向JDK问题,因为malloc调用导致内存泄漏的唯一吸烟枪,理论上应该来自JVM代码。
和你一样,我发现升级JDK解决了这个问题。我在这里发布答案的原因是因为我知道它解决问题的原因 - 它是在JDK8中修复的JDK错误u152:https://bugs.openjdk.java.net/browse/JDK-8164293
错误报告提到Class / malloc增加,而不是Thread / arena,但是其中一条评论进一步说明错误再现清楚地显示了线程/竞技场的增加。
答案 4 :(得分:1)
Java 8更新152没有提供此问题。尚未明确确定早期版本的原因。