Multithreading Java8中javaw进程的私有字节数增加

Multithreading Java8中javaw进程的私有字节数增加,multithreading,java-8,java-native-interface,native,java-7,Multithreading,Java 8,Java Native Interface,Native,Java 7,我的项目已经开始使用Java7中的Java8 在切换到Java8之后,我们看到了一些问题,比如随着时间的推移,内存消耗越来越高 以下是我们所做的调查: 问题只有在从java7和java8迁移之后才会出现 因为元空间是唯一与内存相关的东西,它从hava 7变为java 8。我们监控了元空间,其增长不会超过20MB 堆也保持一致 现在剩下的唯一途径是分析内存如何分配到Java7和Java8中的进程,特别是私有字节内存。如有任何想法或链接,将不胜感激 注意:这个javaw应用程序是一个基于swin

我的项目已经开始使用Java7中的Java8

在切换到Java8之后,我们看到了一些问题,比如随着时间的推移,内存消耗越来越高

以下是我们所做的调查:

  • 问题只有在从java7和java8迁移之后才会出现
  • 因为元空间是唯一与内存相关的东西,它从hava 7变为java 8。我们监控了元空间,其增长不会超过20MB
  • 堆也保持一致
现在剩下的唯一途径是分析内存如何分配到Java7和Java8中的进程,特别是私有字节内存。如有任何想法或链接,将不胜感激

注意:这个javaw应用程序是一个基于swing的应用程序

更新1:使用NMT工具分析本机内存并生成与基线相比的内存占用差异。我们发现堆保持不变,但是线程正在泄漏所有内存。因此,由于堆没有变化,我假设此泄漏是由于本机代码造成的。

因此,挑战仍然存在。任何关于如何分析所有线程占用的内存的想法都将在这里有所帮助。 下面是从本机内存跟踪中获取的快照

在这张图片中,您可以看到线程增加了88MB。竞技场和资源手柄数量增加了很多

在这张图片中,您可以看到在这个Malloc中增加了73mb。但是这里没有显示方法名称。


因此,请在理解这两个屏幕截图时提供一些信息。

您可以尝试另一个GC实现,如Java7和Java中引入的G1。要做到这一点,只需使用以下工具启动Java应用程序:

-XX:+UseG1GC
Java 8u20中的G1 GC还有一个有趣的功能,可以在堆中查找重复的字符串并“消除”它们(这仅在激活G1时有效,而不使用默认Java 8的GC)

在进行此类更改投入生产之前,请注意彻底测试您的系统


考虑优化JVM选项

  • 并行收集器(吞吐量收集器)

    -XX:+UseParallelGC

  • 并发收集器(低延迟收集器)

    -XX:+UseConMarkSweepGC

  • 使用字符串重复项删除程序

    -XX:+UseStringDuplication

  • 优化压缩比

    -压缩比: 及转介

  • 在本文中,您可以看到如何分析JVM的本机内存以查找内存泄漏的信息和参考。很快,请看

    更新

    您是否使用了-XX:NativeMemoryTracking=detail选项?结果很简单,它们表明malloc分配的内存最多。:)有点明显。下一步是评测应用程序。为了分析本机方法和Java,我使用(我们在生产中使用)带有perf_事件的flame图。看看这个,好的开始


    请注意,线程的内存增加了,很可能是应用程序中的线程增加了。在执行之前,我建议分析前后的线程转储,以检查Java线程数是否增长以及为什么增长。您可以通过jstack/jvisualvm/jmc等获得线程转储。

    此问题不随Java 8更新152一起出现。为什么它会出现在早期版本中,其确切的根本原因还没有明确确定

    我遇到了完全相同的问题

    堆使用率不变,只有元空间增加,NMT差异显示线程使用的内存中存在缓慢但稳定的泄漏,特别是在竞技场分配中。我曾试图通过设置MALLOC_ARENAS_MAX=1 env var来修复它,但效果并不理想。使用jemalloc/jeprof分析本机内存分配时,没有发现可归因于客户机代码的泄漏,而是指出了JDK问题,因为只有malloc调用导致内存泄漏,理论上,这应该来自JVM代码

    和你一样,我发现升级JDK解决了这个问题。我在这里发布答案的原因是因为我知道它修复问题的原因-这是JDK8 u152中修复的JDK错误:


    bug报告提到类/malloc的增加,而不是线程/arena,但有一条评论进一步澄清了bug的复制清楚地显示了线程/arena的增加。

    什么样的内存消耗?堆在增长吗?是否占用了更多的本机内存?(这是一些永久发电机被移动的地方)。这个问题太笼统了。您需要显示一些内存分析。转储堆并分析它(例如,使用Eclipse内存分析器)JDK7和JDK8。寻找显著的差异。提交你的调查结果。如果你认为有问题,你应该采取措施来验证是否确实存在问题,如果存在问题,则进行量化。不仅是任务管理器中显示的统计数据,还包括各种java诊断工具打印的统计数据。,但仍然需要更多的信息,如内存转储分析。使用此工具检查本机内存使用情况可能是值得的。更改GC不是一个选项,因为此问题似乎与heap或GC无关。但当heap始终保持不变时,我们为什么要查看GC呢。GC或堆似乎没有问题。对于Java8更新152,这个问题似乎不会出现。。非常感谢您分享缩小调查范围的信息。您的答案中提供了很好的信息,您已经给出了链接。我将不得不用你提供的信息进行测试,并将再次更新你的信息。感谢你的回答,因为它包含了最有用的信息。但我仍然不接受这个答案,因为我仍然需要在我的项目中使用这些信息和测试。如果我们能看到结果,就更有可能给出具体的答案。谢谢,不断更新。@Onki更新。对不起,回复晚了。请不要犹豫,给我写封信引起我的注意
    -XX:+UseStringDeduplication