首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >垃圾收集器无法清除垃圾,导致完全频繁的gc。

垃圾收集器无法清除垃圾,导致完全频繁的gc。
EN

Stack Overflow用户
提问于 2015-05-11 20:21:24
回答 2查看 3.8K关注 0票数 5

我们使用并行gc和1.7.0_71。

代码语言:javascript
复制
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分钟触发一次。通过分析,我们发现每个大小为173 K的180万个char数组对象留在堆中。小gc无法恢复它们。在进行堆转储时,我们在Eclipe的剩余部分找到了许多对象。MAT直方图显示了大量的char数组(它们被呈现为html),但是对于char数组的所有传入引用和GC根的合并路径都是不可访问的,但是只有完整的gc才能恢复它们,而不是小GC。当没有引用对象时,为什么小GC不能恢复它们?日食垫图片附呈。请看所有的参考资料是无法到达的。

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

修复之前,有对HttpServletRequest对象的挂起引用。

所有与此问题相关的图片:Pm7a?dl=0

总体堆

堆直方图视图

现在的问题是

  1. 你认为这是垃圾收集器的问题吗?我们将JBoss 7.1.1升级为野蝇8.2.0.Final。gc策略和JDK版本没有变化。为什么gc不能回收它指向不可访问引用的内存。
  2. 我们可以将XX:NewRatio降低到1。但是,我们不确定这是否会起作用,因为完全gc经常发生。
  3. 你认为搬到G1 GC会有帮助吗?吞吐量会否下降?G1 GC的最佳可用选项是什么。我们的堆大小-Xms :1024米,-Xmx 2048米。我们没有看到内存泄漏,内存中没有error.Attaching完整的gc日志输出 2015-05-10 19:32:41 IST\x{e76f} 459.939:完全GC [PSYoungGen: 8123K->0K(680960K)] [ParOldGen: 782136K->359065K(766464K)] 790260K->359065K(1447424K) [PSPermGen: 202932K->202930K(441344K)],1.0738240秒2015-1019:32:42 IST 462.306: GC [PSYoungGen: 672768K->10534K(685056K)] 1031833K->3696K(1451520K),0.0450800秒2015-05-1010 19:PSYoungGen:PSYoungGen [PSYoungGen: 2727689K(685056K)]1031833K->3696K(1451520K)[PSYoungGen: 681349K->9812K(686080K)] 1045341K->377511K(1452544K);0.0439060秒2015-105-1019:32:46 IST 466.283:[PSYoungGen: 683092K->10733K(686080K)] 1050791K->383554K(1452544K),0.0464700秒2015-105-1019:32:48 IST 467.659: GC [PSYoungGen: 684013K->11283K(685568K)] 1056834K->3881K(20532K),0.1381130秒2015-05-10 19:32:50 IST\x{e76f} 469.734: GC [PSYoungGen: 684051K->9652K(686080K)] 1061419K->393759K(1452544K),0.0466800秒2015-05-1019:32:51 IST x 471.087: GC [PSYoungGen: 682420K->11253K(685568K)] 1066527K->400087K(1452032K),0.0589180秒2015年05-1019:32:52 IST 472.325: GC [PSYoungGen: 684021K->7957K(686080K)] 1072855K>403018K(44525K),0.0436140秒2015-05-10 19:32:54 IST\x{e76f} 473.606: GC [PSYoungGen: 680725K->9177K(685056K)] 1075786K->406493K(1451520K),0.0524990秒2015-05-1010 19:34:34 IST x 573.526: GC [PSYoungGen: 684217K->10956K(686080K)] 1440629K->771626K(1452544K),0.0416620秒2015-105-1019:34 IST 573.568:[完整PSYoungGen: 10956K->0K(686080K) 771626K> PSPermGen: 476930-20830K(20830K)>时代: user=2.46 sys=0.01 real=0.80 2015-10 19:34:36 IST 575.600: GC [PSYoungGen: 674304K->10465K(686592K)] 1039262K->375423K(1505280K) 0.0410330秒2015-05-1019:36:35 IST 694.277: GC [PSYoungGen: 684413K->9342K(687104K)] 1490469K->820033K(1505792K),0.2160320秒2015-1019:36:36 IST 695.664:[PSYoungGen: 684670K->8323K(687104K)][PSYoungGen: 8323K->0K(687104K)] [ParOldGen: 815056K->363295K(838144K)] 823380K->363295K(1525248K) [PSPermGen: 203095K->203095K(401920K)],0.8133080秒2015-1019:36:38 IST 697.669: GC [PSYoungGen: 675328K->10586K(686592K)] 1038623K->373882K(1524736K),0.0436000 s.
EN

回答 2

Stack Overflow用户

发布于 2015-05-11 22:57:27

当没有引用对象时,为什么小GC不能恢复它们?

很可能是因为他们是老一代。小GCs只在年轻一代中处理不可到达的对象。

这种情况通常发生在物体寿命比年轻一代的寿命长的时候。例如,如果涉及缓存,将结果保存一段时间,或者请求生存期超过GC interval * tenuring threshold时。

-XX:+PrintTenuringDistribution可能被证明是有用的。

首先,您可以尝试通过-XX:MaxGCPauseMillis=...提供一个暂停时间目标。ParallelGC可能会遇到它。

如果这没有帮助,您可以重构您的代码,以减少对象的生存期,或降低分配率,以减少较小的GC的频率。

请注意,最重要的ParallelGC是吞吐量收集器,就CPU周期而言,它比并发收集器更高效,但它通常无法满足像这些目标那样的低暂停时间目标。

你认为搬到G1 GC会有帮助吗?

如果你关心的是暂停时间,很有可能。您可能还想尝试CMS。

如果您想尝试G1,您可能应该切换到java 8,它的启发式方法随着时间的推移有了很大的改进,而且它还在成熟。

吞吐量会否下降?

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

G1 GC的最佳可用选项是什么。

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

票数 3
EN

Stack Overflow用户

发布于 2015-05-13 00:36:41

类似的问题也发生在我们的网上。一个引用泄露到了Gen1中--并且老化到了第二代,最终导致内存积累成30Gb+大小。

虽然与JAVA没有直接关系,但是我们通过构建一个定制的内存管理器来解决类似的问题,该管理器可以子分配byte[]。这使得我们可以在没有加载GC的情况下存储数亿个在进程中的对象。该解决方案非常适合缓存,而且比进程外Redis/memcache快得多。它用超高速序列化器序列化对象,这样“引用”就变成了“指针”(我们的两个It结构),这样GC就不会被扫描1000000000个对象重载。

参见:7hukyejQ

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30176934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档