我们已启用详细的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--”是什么意思?
答案 0 :(得分:13)
我的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日志中以及原因。
据我所知" Parallel Scavenge" Young Gen是一个停止世界的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("--");
}
}
Young 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的疏散失败是当幸存者区域没有足够空间容纳来自年轻区域的幸存物体时。
我不知道G1收集器是否使用Full GC响应疏散失败。
答案 1 :(得分:1)
我从here获得了以下内容:
前两行表明你有 两个小集合和一个主要 一。之前和之后的数字 箭头表示组合的大小 垃圾前后的活物 收集,分别。经过轻微的 集合包括对象 这不一定是活着但是 无法回收,因为 他们直接活着,或因为 它们位于或引用 终身一代。数字在 括号s总可用 空间,不计算空间 永久的一代,这是 总堆减一个格式 第三行的主要收藏品 类似。国旗 -XX:+ PrintGCDetails打印有关集合的其他信息。该 打印的附加信息 这面旗帜有可能改变 每个版本的虚拟机。 随附的额外输出 -XX:+ PrintGCDetails标志特别随着需要的变化而变化 开发Java Virtual 机。幸存者空间。该 小型收藏约占四分之一 一秒钟。
答案 2 :(得分:1)
实际上,在我们自己的日志中遇到这个问题之后,我和一个同事有一个替代解释,似乎更紧密地符合事实。
在这个例子中你会注意到一个完整的GC跟随这个奇怪的次要GC线。我可以确认,当它在我们的日志中出现时总是如此。您还可以看到Young Gen的开头和结尾大小相等,我可以再次确认情况总是如此。
我们相信这里发生的事情是VM启动了一个次要GC,并且在无法释放任何内容或花费太长时间而无法释放任何内容之后,决定执行Full而不是。
答案 3 :(得分:0)
它不在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()吗?
答案 4 :(得分:0)
Yishai在评论中说:
鉴于时间戳和内存量,我猜它会执行垃圾收集但丢失可用内存(因为其他对象是并行创建的)