Java垃圾收集日志消息


96

我已配置Java将垃圾回收信息转储到日志中(详细GC)。我不确定日志中的垃圾回收项是什么意思。这些条目的示例发布在下面。我在Google上四处搜寻,但找不到可靠的解释。

我有一些合理的猜测,但我正在寻找答案,这些答案提供了对条目中数字含义的严格定义,并有可靠的依据。引用sun文档的所有答案的自动+1。我的问题是:

  1. PSYoungGen指的是什么?我认为这与上一代(年轻人)有关,但是究竟是什么呢?
  2. 第二个三元组与第一个三元组有什么区别?
  3. 为什么要为数字的第一个三元组指定一个名称(PSYoungGen),而没有为第二个三元组指定一个名称(PSYoungGen)?
  4. 三元组中的每个数字(内存大小)是什么意思。例如,在109884K-> 14201K(139904K)中,是GC 109884k之前的内存,然后将其减少为14201K。第三个数字有何关系?为什么我们需要第二组数字?

8109.128:[GC [PSYoungGen:109884K-> 14201K(139904K)] 691015K-> 595332K(1119040K),0.0454530秒]

8112.111:[GC [PSYoungGen:126649K-> 15528K(142336K)] 707780K-> 605892K(1121472K),0.0934560秒]

8112.802:[GC [PSYoungGen:130344K-> 3732K(118592K)] 720708K-> 607895K(1097728K),0.0682690秒]


整个堆,堆的年轻一代的一部分,轻微GC进行GC是如何工作的,检查如cubrid.org/blog/dev-platform/...
MarianP

Answers:


90

GC优化指南》中对此进行了大部分解释(无论如何,您都应该很好地阅读它)。

命令行选项-verbose:gc使有关堆和垃圾收集的信息在每个收集处打印。例如,以下是大型服务器应用程序的输出:

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

在这里,我们看到两个次要收藏,然后是一个主要收藏。箭头前后的数字(例如,325407K->83000K从第一行开始)分别指示垃圾收集之前和之后的活动对象的组合大小。进行次要收集后,大小包括一些垃圾(不再活动)但无法回收的对象。这些对象包含在使用权的世代中,或从使用权的世代或永久代中引用。

括号中的下一个数字(例如,(776768K)从第一行起)是堆的提交大小:即Java对象可使用的空间量,而无需从操作系统请求更多的内存。请注意,该数字不包括幸存者空间之一,因为在任何给定时间只能使用一个幸存者空间,并且也不包括保存虚拟机使用的元数据的永久代。

该行的最后一项(例如0.2300771 secs)指示执行收集所需的时间;在这种情况下,大约需要四分之一秒。

第三行中主要收藏的格式相似。

产生的输出格式-verbose:gc在将来的发行版中可能会更改。

我不确定为什么您有PSYoungGen;您更换垃圾收集器了吗?


在哪里可以找到gc日志文件?
楼先生2012年

7
这个答案并没有真正解决最初的问题。我觉得michaeljoseph的答案更好。它解决了Ethan提出的问题,并且在分解原始示例方面做得更好。尽管他的回答有两个问题(他的链接现在已经死了,并且rafa.ferreria指出了另一个问题),但这不仅仅反驳了Oracle文档。
德克2014年

127
  1. PSYoungGen指用于次要收集的垃圾收集器。PS代表Parallel Scavenge。
  2. 第一组数字是年轻代的大小,第二组是整个堆的大小。(诊断垃圾收集问题详细说明了格式)
  3. 该名称表示所讨论的生成器和收集器,第二组用于整个堆。

相关的完整GC的示例还显示了用于旧世代和永久世代的收集器:

3.757: [Full GC [PSYoungGen: 2672K->0K(35584K)] 
            [ParOldGen: 3225K->5735K(43712K)] 5898K->5735K(79296K) 
            [PSPermGen: 13533K->13516K(27584K)], 0.0860402 secs]

最后,分解示例日志输出的一行:

8109.128: [GC [PSYoungGen: 109884K->14201K(139904K)] 691015K->595332K(1119040K), 0.0454530 secs]
  • GC之前使用107Mb,GC 之后使用14Mb,最大年轻代大小137Mb
  • GC之前使用的675Mb堆,GC 之后使用的581Mb堆,最大1Gb堆大小
  • 自JVM启动以来,次要GC发生 8109.128秒,花费了0.04

8
只是一个小小的注释,“()”之间的值不是最大大小,永远不会是当前的最大大小。如果GC无法释放更少的堆,则此限制将需要更多空间来运行系统,并且该值将增加。当然要
遵守

@ rafa.ferreira我认为括号中的值即1119040K是已提交的堆大小。我认为,GC不会在任何地方打印“最大堆”大小。参考文献1参考文献2
rohitmohta 2015年

23

我只想提一提,您可以通过

-XX:+PrintGCDetails 

参数。然后,您会在答案中看到PSYoungGen或PSPermGen的输出。

-Xloggc:gc.log似乎产生像相同的输出-verbose:gc,但是你可以指定在第一个输出文件。

用法示例:

java -Xloggc:./memory.log -XX:+PrintGCDetails Memory

为了更好地可视化数据,您可以尝试gcviewer(可以在github上找到更新的版本)。

注意正确编写参数,我忘记了“ +”,并且我的JBoss无法启动,没有任何错误消息!


3
请注意,重新启动Java时gc.log将被覆盖(例如,如果您的tomcat因为存在内存问题而重新启动,那么您将很乐意看到该gc.log)。或者,如果您轮换GC日志,至少会这样。还有许多其他选项可控制gc日志记录。请参阅oracle.com/technetwork/articles/java/vmoptions-jsp-140102.html。特别要考虑-XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<some number of files> -XX:GCLogFileSize=<some size> -XX:+PrintTenuringDistribution
Dan Pritts
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.