Java垃圾收集:次要,主要,完整

时间:2014-09-08 12:22:56

标签: java garbage-collection

我试图在大型企业Java应用程序中暂停垃圾收集。我有GC日志并开始使用各种工具查看它们 - 此处的屏幕截图是使用GCViewer完成的。 (遗憾的是,没有更详细的GC信息的日志......)

我还在阅读我们正在使用的Java Hotspot VM垃圾收集。

但我仍然有些困惑:下面是GC图表放大部分的屏幕截图。

Zoom on garbage collection graph

这里有三件事:

  1. 有"小曲折"蓝线(你几乎看不到):据我所知,这些是 gc周期在Young空间中徘徊。
  2. 有黑色条,这是一个阻塞的10s全GC,如日志中所示:

    1751585.394: [Full GC 1433326K->660045K(1552832K), 10.1157600 secs]
    
  3. 然后就是"大曲折"蓝线(显示在左侧的下降)。 这让我感到困惑。
  4. 模式#3的日志不会将其标记为完整的GC,但看起来与其他类似...

        1749795.648: [GC 1299871K(1552832K), 0.0402933 secs]
    
    • 这也是一个小型GC吗?
    • 如果是,为什么同时发生两种不同的小型垃圾收集模式(#1和#3)?
    • 或者在Young空间中的小型GC和Tenured中的完整GC之间还有其他什么东西?

    编辑。一些额外的信息:
    使用的GC:并行Mark-Sweep GC
    吞吐量为93.8%
    最长暂停:10.116秒
    暂停时间:6.21%

3 个答案:

答案 0 :(得分:2)

Java的分代垃圾收集器有几种不同的“种类”的垃圾收集。正如你所提到的,“小zig-zags”是年轻空间中的小型收藏品,黑色条形图将是一个完整的垃圾收集。为简单起见,我将描述正在发生的事情中最重要的部分。

年轻一代被划分为“伊甸园”空间一个或多个“幸存者”空间。在其中一个小的锯齿形中,伊甸园空间中的死亡物体被移除,活体物体被移动到一个幸存者空间。这是一个非常快速的操作,因为世代假设表明大多数对象将是短暂的。幸存者空间的后续扫描可以将仍然存活的对象从幸存者空间移动到终身生成中。这仍然被视为次要收藏。

我怀疑你在第一次大跌中所看到的实际上是从幸存者一代到终身一代的“晋升”。

终身代是所有年轻一代都不够年轻的东西(这意味着像许多其他GC选项一样可调)。终生代比年轻一代大得多,因此需要花费大量时间来扫除。当你谈到一个“完整的”垃圾收集时,这指的是对终生代的扫描(除了年轻一代)。

CMS垃圾收集器对其执行的大部分操作同时运行,但仍需要stop the world来完成年轻和终身的标记操作。 CMS收集器应该非常快,即使对于大堆也是如此。但是,还有一种情况是CMS阻止了这个世界:concurrent mode failure

暂停的第二次大幅下降可能是由于这种情况造成的,这种情况发生在终身发电过剩时。您可以调整终身代的大小和其他参数以避免这些。

答案 1 :(得分:0)

我怀疑这是并发扫描。要确认,必须使用以下

进行监控
-verbose:gc -XX:+PrintGCDetails

假设图表显示年轻+终身一代,这不能像乔纳森所提到的那样从幸存者世代升到终身一代。

答案 2 :(得分:0)

根据您的日志,我会说:

1)这是一个小集合。正如@Eugene上面所说,它很短,并没有被标记为完整的gc。

2)此时应用程序中有两种短期对象。一些非常短命的“持续”在这些小曲折中的两个之间的时间量。而一些寿命较长的,仍然没有足够长的时间被提升为终身一代,并且在混乱的小集合之前的某个时刻有资格收集垃圾。

可能还有其他解释,但我不相信你可以从你的内容中得知。

如果你担心它(或者你可能只是好奇的话),我会启用更详细的gc日志记录,并使用访问日志之类的日志来尝试将应用程序活动与drop关联起来。