问题 “垃圾收集日志”中的“GC--”是什么意思?


我们打开了详细的GC日志记录来跟踪已知的内存泄漏并在日志中获得以下条目:

...
3607872.687: [GC 471630K->390767K(462208K), 0.0325540 secs]
3607873.213: [GC-- 458095K->462181K(462208K), 0.2757790 secs]
3607873.488: [Full GC 462181K->382186K(462208K), 1.5346420 secs]
...

我理解第一个和第三个,但“GC--”是什么意思?


12390
2017-07-23 23:05


起源

给定时间戳和内存量,我猜它会执行垃圾收集但丢失可用内存(因为其他对象是并行创建的) - Yishai
Yishai,谢谢,这很有道理。不确定它是否正确,但非常好。 - RodeoClown
想把它放在一个答案中,这样我可以投票/接受它吗? :) - RodeoClown
您使用的是哪个版本的JDK?完整版,请。 - Trenton
@trenton:JDK 1.6.0.12 - RodeoClown


答案:


我的gc输出中有这些行:

44871.602: [GC-- [PSYoungGen: 342848K->342848K(345600K)] 961401K->1041877K(1044672K), 0.1018780 secs] [Times: user=0.16 sys=0.00, real=0.11 secs]

我读了Yishai的答案,这是有意义的,但我想在Java GC源代码中看到它,当JVM在GC日志中打印“ - ”时为什么。

因为据我所知,Young Gen的“Parallel Scavenge”是一个停止世界的GC,所以就在那里 不能是任何并行创建的对象 到这个GC。 (看到 https://blogs.oracle.com/jonthecollector/entry/our_collectors

你可以在jdk源代码中找到它(参见 http://hg.openjdk.java.net/jdk7/jdk7) g1CollectedHeap.cpp和psScavenge.cpp

jdk7-ee67ee3bd597/hotspot/src/share$ egrep -h -A2 -B5 -r '"\-\-"' *
# G1 Collector
if (evacuation_failed()) {
  remove_self_forwarding_pointers();
  if (PrintGCDetails) {
    gclog_or_tty->print(" (to-space overflow)");
  } else if (PrintGC) {
    gclog_or_tty->print("--");
  }
}
--
# Parallel Scavenge Collector
promotion_failure_occurred = promotion_failed();
if (promotion_failure_occurred) {
  clean_up_failed_promotion();
  if (PrintGC) {
    gclog_or_tty->print("--");
  }
}

GC - 与Parallel Scavenge Collector的原因

年轻的GC遇到促销失败(见 http://mail.openjdk.java.net/pipermail/hotspot-gc-use/2010-March/000567.html):

促销失败是一种不成功的清除,因为旧世界没有足够的空间来进行所有必要的促销活动。清除     本质上是解开的,然后完成整个堆的完整STW压缩。

“没有足够的空间”并不一定意味着旧的空间不足,但旧空间严重破碎(见 http://blog.ragozin.info/2011/10/java-cg-hotspots-cms-and-heap.html):

[...]即使可用字节总数足够大,也无法找到一定量的连续内存来促进特定的大型对象。

这两个JVM选项可以帮助您分析堆碎片(请参阅 http://blog.ragozin.info/2011/10/java-cg-hotspots-cms-and-heap.html):

-XX:+PrintPromotionFailure
-XX:PrintFLSStatistics=1

使用G1收集器的GC的原因

G1的疏散失败是当幸存者区域没有足够空间容纳来自Young Region的幸存物体时。

我不知道G1收集器是否用Full GC响应疏散失败。


13
2018-05-04 11:28



嗯,看起来很明确:) - RodeoClown


我得到了以下内容 这里

前两行表明你有   两个小集合和一个主要   一。之前和之后的数字   箭头表示组合的大小   垃圾前后的活物   收集,分别。经过轻微的   集合计数包括对象   这不一定是活着但是   无法回收,因为   他们直接活着,或者因为   它们位于或引用   终身一代。中的数字   括号s总可用   空间,不计算空间   永久的一代,这是   总堆减一个格式   第三行的主要收藏品   很相似。国旗   -XX:+ PrintGCDetails打印有关集合的其他信息。该   打印的附加信息   这面旗子有可能改变   每个版本的虚拟机。   随附的额外输出   -XX:+ PrintGCDetails标志特别随着需要的变化而变化   开发Java Virtual   机。幸存者空间。该   小型收藏约占四分之一   一秒钟


1
2017-07-23 23:17





实际上,在我们自己的日志中遇到这个后,我和一个同事有一个替代解释,似乎更紧密地符合事实。

在这个例子中你会注意到Full GC遵循这个奇怪的次要GC线。我可以确认,当它在我们的日志中出现时总是如此。您还可以看到Young Gen的开始和结束大小相等,我可以再次确认情况总是如此。

我们相信这里发生的事情是VM已经开始使用Minor GC,并且在无法释放任何内容或花费太长时间而无法释放任何内容之后,决定执行Full。


1
2017-08-25 23:10





它不在Java GC FAQ上

http://java.sun.com/docs/hotspot/gc1.4.2/faq.html

也不像Java GC示例页面中提到的那样

http://java.sun.com/docs/hotspot/gc1.4.2/example.html

我以前从未见过。

你有没有特殊的垃圾收集器运行? 你在运行什么VM? 它是否始终在Full GC之前发生? 你在调用System.gc()吗?


0
2017-07-23 23:16



嗨e5,没有特殊的垃圾收集器。普通的Sun VM。我只偶尔看到它,所以不,它不是每个完整的GC之前(但我不能说每次它发生时它是直接在一个之前)。没有System.gc()。 - RodeoClown


伊沙伊 在评论中说:

给定时间戳和内存量,我猜它会执行垃圾收集但丢失可用内存(因为其他对象是并行创建的)


0
2017-08-24 23:23