Java 主要和次要垃圾收集

2022-01-16 00:00:00 garbage-collection java

我一直在阅读 Java 中的垃圾收集和 SO Q&A,但我对垃圾收集的类型感到困惑.

我们以吞吐量收集器为例.(又名并行收集器).文档说它使用多个线程来执行 Minor 集合,并为 Major 集合使用单线程(与串行收集器相同).

现在我的问题:

  1. Full GC 是什么意思:a) 是否意味着 Minor 和 Major 收集都已完成?或者 b) Full GC == Major Collections?是哪一个?
  2. 如果 a),是否意味着 Minor Collection 仍然使用多个线程完成,而 Major Collection 使用 Single 完成?
  3. 如果是 b),是否意味着 Young 和旧代是使用单线程清除的吗?

另外,4. Full GC 是否也只影响 OldGeneration 或 YoungGeneration?

提前致谢.

解决方案

让我解释一下.

<块引用><块引用>

我们以吞吐量收集器为例.(又名并行收集器).文档说它使用多个线程来执行 Minor 集合,并使用单个线程来执行 Major 集合(与 Serial 收集器相同).

这里有一点要理解.默认情况下,在大多数较新的系统上,JVM 为年轻代和老年代使用两个不同的垃圾收集器.在我的机器上:我有 Parallel New Collector 用于年轻代,并发标记和扫描收集器用于老一代.

当 JVM 无法为新对象分配空间时触发 Minor Collection(请记住:新对象总是分配在年轻一代的伊甸园区域).

下一个问题:

<块引用><块引用>

Full GC 是什么意思:a) 这是否意味着 Minor 和 Major 收集都已完成?或者 b) Full GC == Major Collections?是哪一个?

和,

<块引用><块引用>

另外,4. Full GC 是否也只影响 OldGeneration 或 YoungGeneration?

这取决于.JVM 将每个 Major Collection 报告为 Full GC.[尝试使用这些标志 java -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamp].学究式的定义是 Full GC 先运行 Minor,然后运行 ​​Major(尽管如果老年代已满,则可以切换顺序,在这种情况下,它首先被释放以允许它从年轻代接收对象).

好的,回到正题.JVM 将 Major Collection [in the Older (or Perm) Generation] 视为 Full GC.以下是我能够快速编写的程序的输出来说明这一点.第一行是 Minor GC,第二行是 Major (Full) GC.您可以看到它只发生在老年代 (CMS) 中,并且能够将老年代从 1082K 减少到 1034K.

  • 11.431: [GC 11.431: [ParNew: 1152K->128K(1152K), 0.0009893 secs] 2111K->1210K(6464K), 0.0010182 secs] [Times: user=0.00 sys=0.00, real=0.00 秒]
  • 17.882: [Full GC (System) 17.882: [CMS: 1082K->1034K(5312K), 0.0212614 secs] 2034K->1034K(6464K), [CMS Perm : 9426K->9410K(21248K)], 0.0213200 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

下一个问题:

<块引用><块引用>

如果 a),是否意味着 Minor Collection 仍然使用多线程完成,而 Major Collection 使用 Single 完成?

是的.请参阅我的答案的开头.年轻代和老一代由不同的收集器提供服务.对于年轻代,您可以使用以下任何一种:

  • -XX:+UseSerialGC
  • -XX:+UseParallelGC
  • -XX:+UseParNewGC

对于老年代,可用的选择是:

  • -XX:+UseParallelOldGC
  • -XX:+UseConcMarkSweepGC

I have been reading up on Garbage Collection in Java and SO Q&A but I'm confused about types of Garbage Collection.

Let's take Throughput Collector as an example. (aka Parallel Collector). The docs say it uses multiple threads to do the Minor collections and single thread for Major collections (same as Serial collector).

Now my questions:

  1. What does it mean by a Full GC: a) Does it mean both Minor and Major collections are done? Or b) Full GC == Major Collections? Which one is it?
  2. If a), does it mean that the Minor Collection is still done using multiple threads whereas the Major was done using Single?
  3. If b), does it mean both Young & Old Generations were cleared using Single Thread?

Also, 4. Does Full GC only affect OldGeneration or YoungGeneration as well?

Thanks in advance.

解决方案

Let me explain.

Let's take Throughput Collector as an example. (aka Parallel Collector). The docs say it uses multiple threads to do the Minor collections and single thread for Major collections (same as Serial collector).

Here's something to understand. By default, on most newer systems, JVM uses TWO different Garbage Collectors for Young and Old Generations. On my my machine: I have Parallel New Collector for the Young Generation and Concurrent Mark and Sweep Collector for the Older Generation.

Minor Collection is triggered when then JVM is unable to allocate space for a new Object (Remember: new objects are always allocated in Young Generation's Eden Area).

Next Question:

What does it mean by a Full GC: a) Does it mean both Minor and Major collections are done? Or b) Full GC == Major Collections? Which one is it?

and,

Also, 4. Does Full GC only affect OldGeneration or YoungGeneration as well?

It depends. JVM reports every Major Collection as Full GC. [Try with these flags java -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamp]. The pedantic definition is that Full GC runs Minor first followed by Major (Although the order could be switched if the Older Generation is full in which case it is freed first to allow it to receive objects from the Young Generation).

OK, back to the point. JVM considers Major Collection [in the Older (or Perm) Generation] as Full GC. Below are outputs from a program I was able to quickly write to illustrate the point. The first line is Minor GC and the second is Major (Full) GC. You can see that it only happened in the Older Generation (CMS) and was able to reduce old generation from 1082K to 1034K.

  • 11.431: [GC 11.431: [ParNew: 1152K->128K(1152K), 0.0009893 secs] 2111K->1210K(6464K), 0.0010182 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
  • 17.882: [Full GC (System) 17.882: [CMS: 1082K->1034K(5312K), 0.0212614 secs] 2034K->1034K(6464K), [CMS Perm : 9426K->9410K(21248K)], 0.0213200 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

Next question:

If a), does it mean that the Minor Collection is still done using multiple threads whereas the Major was done using Single?

Yes. See the beginning of my answer. Young and Older Generations are served by different Collectors. For Young Generation, you can use any one of the following:

  • -XX:+UseSerialGC
  • -XX:+UseParallelGC
  • -XX:+UseParNewGC

For Old Generation, the available choices are:

  • -XX:+UseParallelOldGC
  • -XX:+UseConcMarkSweepGC

相关文章