什么是;通用条款--;在java垃圾收集日志中是什么意思?

什么是;通用条款--;在java垃圾收集日志中是什么意思?,java,logging,garbage-collection,Java,Logging,Garbage Collection,我们已启用详细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日志记录以跟踪已知内存泄漏,并在日志中获得以下条目:

...
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--”一词是什么意思呢?

它不在Java GC常见问题解答中

Java GC示例页面中也没有提到类似的内容

我以前从未见过这种情况

你们有运行特殊的垃圾收集器吗? 你在运行什么虚拟机? 它总是在完全GC之前发生吗? 您是否正在调用System.gc()?

我从中获得以下信息:

前两行表示您有 两个小系列和一个大系列 一个。数字前后 箭头指示的是 垃圾之前和之后的活动对象 分别收集。小调后 集合计数包括对象 它们不一定是活着的,但是 也不能回收,因为 他们直接活着,或者是因为 它们位于或从中引用 终身一代。中的数字 括号中是可用的总数 空间,不计算空间中的空间 永久一代,即 总堆数减去 第三行的主要收藏 这是相似的。旗帜 -XX:+PrintGCDetails打印有关集合的附加信息。这个 附加信息以 此标志可能随时间而变化 虚拟机的每个版本。 使用 -XX:+PrintGCDetails标志会根据客户的需要进行特定更改 Java虚拟机的开发 机器。幸存者空间的一部分。这个 小规模收集花费了大约四分之一的时间 一秒钟

在评论中说:


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


事实上,在我们自己的日志中遇到这个问题后,我和一位同事有了另一种更符合事实的解释

在本例中,您会注意到完整的GC遵循这个奇怪的次要GC行。我可以证实,当它出现在我们的日志中时,情况总是如此。你们也可以看到,年轻一代的开始和结束大小是相等的,我可以再次证实,情况总是如此


我们认为,这里发生的事情是,VM启动了一个小型GC,在无法释放任何内容或花费太长时间而无法释放任何内容后,决定执行完整的GC输出。

我在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日志中打印“-”时,以及为什么

因为据我所知,年轻一代的“并行清理”是一个停止世界GC,所以不可能有任何对象与此GC并行创建。(见附件)

您可以在jdk源代码中找到这一点(请参阅) 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的原因——使用并行清除收集器 年轻的GC遇到升级失败(请参阅):

升级失败是一种无法成功的清除,因为旧版本中没有足够的空间来执行所有需要的升级。清道夫 基本上是展开,然后对整个堆进行完整的STW压缩

“没有足够的空间”并不一定意味着旧空间中没有足够的空间,但旧空间严重碎片化(请参阅):

[…]即使可用字节的总数足够大,也不可能找到一定数量的连续内存来升级特定的大型对象

这两个JVM选项可以帮助您分析堆碎片(请参阅):

GC的原因——使用G1收集器 G1的疏散失败是当幸存者区域没有足够的空间容纳年轻区域中幸存的物体时


我不知道G1收集器是否以完整GC响应疏散故障。

考虑到时间戳和内存量,我猜它执行了垃圾收集,但丢失了可用内存(因为其他对象是并行创建的)Yishai,谢谢,这很有意义。不确定它是否正确,但很有可能。想把它写进一个答案中,这样我就可以投赞成票/接受它吗?:)您使用的是哪个版本的JDK?完整版本。嗨e5,没有特殊的垃圾收集器。正常Sun虚拟机。我只是偶尔看到它,所以不,它不是在每一个完整的GC之前(但我不能说它是否每次都发生在一个GC之前)。没有System.gc()
-XX:+PrintPromotionFailure
-XX:PrintFLSStatistics=1