Java 垃圾收集器无法清除垃圾,导致频繁的垃圾收集

Java 垃圾收集器无法清除垃圾,导致频繁的垃圾收集,java,memory-leaks,jboss,garbage-collection,jvm,Java,Memory Leaks,Jboss,Garbage Collection,Jvm,我们使用1.7.0_71的并行gc java -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -version -XX:InitialHeapSize=258222272 -XX:MaxHeapSize=4131556352 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedOops -XX:+UseParallelGC java version "1.7.0_71"

我们使用1.7.0_71的并行gc

java -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -version
-XX:InitialHeapSize=258222272 -XX:MaxHeapSize=4131556352 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedOops -XX:+UseParallelGC 
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)
我们看到应用程序中每隔几分钟就有大量垃圾在正常负载下产生。次要gc每几秒钟触发一次,主要gc每2分钟触发一次。通过分析,我们发现堆中有180万个字符数组对象,每个对象的大小为173K。次要gc无法恢复它们。在进行heapdump时,我们在Eclipe MAT的剩余部分中发现了许多对象。MAT histogram显示了大量的字符数组(它们被呈现为html),但是所有传入的引用和到字符数组的gc根的合并路径都是不可访问的,但是只有完整的gc才能恢复它们,而不是次要的gc。当没有被引用的对象时,为什么次要GC无法恢复它们?日食垫图片附呈。 请查看无法访问的所有引用

有一些对请求对象的引用,通过设置null来清除它们

在修复之前,存在对HttpServletRequest对象的挂起引用

与此问题相关的所有图像:

总堆

堆直方图视图 现在的问题是

  • 你认为这是垃圾收集器的问题吗?我们将JBoss7.1.1升级到wildfly 8.2.0.Final。gc策略和JDK版本没有变化。为什么gc不能回收指向不可访问引用的内存

  • 我们可以将XX:NewRatio减少到1。但是,我们不确定这是否会起作用,因为完整gc经常发生

  • 你认为迁移到G1 GC会有帮助吗?吞吐量会下降吗?G1 GC的最佳选项是什么。我们的堆大小-Xms:1024m,-xmx2048m。永久发电机512m 我们没有看到内存泄漏,没有内存不足错误。正在连接完整的gc日志输出

    2015-05-10 19:32:41 IST| 459.939: [Full GC [PSYoungGen: 8123K->0K(680960K)] [ParOldGen: 782136K->359065K(766464K)] 790260K->359065K(1447424K) [PSPermGen: 202932K->202930K(441344K)], 1.0738240 secs] [Times: user=3.37 sys=0.01, real=1.07 secs]
    2015-05-10 19:32:42 IST| 462.306: [GC [PSYoungGen: 672768K->10534K(685056K)] 1031833K->369600K(1451520K), 0.0450800 secs] [Times: user=0.15 sys=0.00, real=0.04 secs]
    2015-05-10 19:32:44 IST| 463.641: [GC [PSYoungGen: 682790K->9093K(685568K)] 1041856K->373085K(1452032K), 0.0570820 secs] [Times: user=0.16 sys=0.00, real=0.06 secs]
    2015-05-10 19:32:45 IST| 464.936: [GC [PSYoungGen: 681349K->9812K(686080K)] 1045341K->377511K(1452544K), 0.0439060 secs] [Times: user=0.12 sys=0.00, real=0.04 secs]
    2015-05-10 19:32:46 IST| 466.283: [GC [PSYoungGen: 683092K->10733K(686080K)] 1050791K->383554K(1452544K), 0.0464700 secs] [Times: user=0.14 sys=0.00, real=0.05 secs]
    2015-05-10 19:32:48 IST| 467.659: [GC [PSYoungGen: 684013K->11283K(685568K)] 1056834K->388651K(1452032K), 0.1381130 secs] [Times: user=0.30 sys=0.00, real=0.14 secs]
    2015-05-10 19:32:50 IST| 469.734: [GC [PSYoungGen: 684051K->9652K(686080K)] 1061419K->393759K(1452544K), 0.0466800 secs] [Times: user=0.13 sys=0.00, real=0.05 secs]
    2015-05-10 19:32:51 IST| 471.087: [GC [PSYoungGen: 682420K->11253K(685568K)] 1066527K->400087K(1452032K), 0.0589180 secs] [Times: user=0.11 sys=0.00, real=0.06 secs]
    2015-05-10 19:32:52 IST| 472.325: [GC [PSYoungGen: 684021K->7957K(686080K)] 1072855K->403018K(1452544K), 0.0436140 secs] [Times: user=0.13 sys=0.00, real=0.04 secs]
    2015-05-10 19:32:54 IST| 473.606: [GC [PSYoungGen: 680725K->9177K(685056K)] 1075786K->406493K(1451520K), 0.0524990 secs] [Times: user=0.13 sys=0.00, real=0.05 secs]
    
    2015-05-10 19:34:34 IST| 573.526: [GC [PSYoungGen: 684217K->10956K(686080K)] 1440629K->771626K(1452544K), 0.0416620 secs] [Times:  user=0.14 sys=0.00, real=0.04 secs]
     2015-05-10 19:34:34 IST| 573.568: [Full GC [PSYoungGen: 10956K->0K(686080K)] [ParOldGen: 760670K->364958K(818688K)] 771626K->364958K(1504768K) [PSPermGen: 203069K->203069K(420864K)], 0.8001740 secs] >[Times: user=2.46 sys=0.01, real=0.80 secs]
    2015-05-10 19:34:36 IST| 575.600: [GC [PSYoungGen: 674304K->10465K(686592K)] 1039262K->375423K(1505280K), 0.0410330 secs] [Times: user=0.13 sys=0.00, real=0.04 secs]
    2015-05-10 19:36:35 IST| 694.277: [GC [PSYoungGen: 684413K->9342K(687104K)] 1490469K->820033K(1505792K), 0.2160320 secs] [Times: user=0.55 sys=0.08, real=0.21 secs]
    2015-05-10 19:36:36 IST| 695.664: [GC [PSYoungGen: 684670K->8323K(687104K)] 1495361K->823380K(1505792K), 0.0454050 secs] [Times: user=0.11 sys=0.00, real=0.05 secs]
    2015-05-10 19:36:37 IST| 695.710: [Full GC [PSYoungGen: 8323K->0K(687104K)] [ParOldGen: 815056K->363295K(838144K)] 823380K->363295K(1525248K) [PSPermGen: 203095K->203095K(401920K)], 0.8133080 secs] [Times: user=2.43 sys=0.01, real=0.81 secs]
    2015-05-10 19:36:38 IST| 697.669: [GC [PSYoungGen: 675328K->10586K(686592K)] 1038623K->373882K(1524736K), 0.0436000 secs] [Times: user=0.13 sys=0.00, real=0.04 secs]
    ...
    ....
    
  • 当没有被引用的对象时,为什么次要GC无法恢复它们

    很可能是因为他们是老一代人。次要地面军事系统仅处理年轻一代中无法到达的对象

    这通常发生在对象由于使用寿命超过其在年轻一代中的寿命时。例如,如果所涉及的缓存将结果保留一段时间,或者当请求生存期超过
    GC interval*tenuring threshold
    的生存期时

    -XX:+PrintTenuringDistribution
    可能会提供信息

    首先,您可以尝试通过
    -XX:MaxGCPauseMillis=…
    简单地提供暂停时间目标。ParallelGC可能会满足这一要求

    如果这对你没有帮助,你可以重构你的代码来减少对象的生命周期,或者降低分配率来减少次要的GCs

    请注意,最重要的ParallelGC是一个吞吐量收集器,就CPU周期而言,它比并发收集器效率更高,但它通常无法达到那些低暂停时间目标

    你认为迁移到G1 GC会有帮助吗

    如果您担心暂停时间,很可能是。您可能还想尝试CMS

    如果您想尝试G1,您可能应该切换到Java8,它的启发式随着时间的推移已经改进了很多,而且它仍然在成熟

    吞吐量会下降吗

    可能吧。这取决于是否有备用CPU容量以及如何定义/测量吞吐量。 即使在不太有利的情况下,降幅也可能不大

    G1 GC的最佳选项是什么


    G1应该是自调优的(超出了同样适用于ParallelGC的用户提供的暂停和吞吐量目标)。因此,只需启用它,看看它是否提供了可接受的性能。

    类似的问题也发生在>NET中。一个引用泄漏到Gen1-中,并老化到Gen2中,最终导致RAM累积到30Gb+大小

    尽管与JAVA没有直接关系,但我们通过构建一个自定义内存管理器来解决类似的问题,该管理器分配字节[]。这使我们能够在不加载GC的情况下连续几天存储数亿个进程中的对象。该解决方案非常适合缓存,并且比进程外Redis/memcache快得多。它使用超高速序列化程序序列化对象,这样“引用”就变成了“指针”(我们的两个int的结构),这样GC就不会因扫描100000000个对象而过载

    见此:

    无法发布超过2个链接。添加第三个链接。此屏幕截图显示了对undertow HttpServletRequest的活动引用。MAT图片在修复之前请将其作为内联图片发布。例如,您的应用程序分配了太多的对象,因此您的html表示通常直接在旧一代中分配,而没有年轻->生存部分。解决方案之一是减少-XX:NewRation并增加-XX:maxtenuringthreshold。我们无法通过调整gc设置来减少垃圾。然而,我们设法修复了应用程序中发生的冗余调用。这减少了垃圾的产生。我必须同意,冗余调用增加了请求处理时间,这导致短寿命对象升级到旧一代。