原来书中说的 JVM 默认垃圾回收器是错的!
-XX:+UseCompressedOops?
-XX:+UseParallelGC
java?version?"1.8.0_162"
Java(TM)?SE?Runtime?Environment?(build?1.8.0_162-b12)
Java?HotSpot(TM)?64-Bit?Server?VM?(build?25.162-b12,?mixed?mode)
第 6 行我们可以看到使用的是 -XX:+UseParallelGC 按照书中或者是网上的文章发现,设置这个参数以后默认就是如下两个组合,新生代用 Parallel Scavenge 老年代用 Serial Old
Parallel Scavenge + Serial Old
那么这里再详细科普一下,下面是每个参数对应的回收器的类型
![](https://static001.geekbang.org/infoq/10/10bc6d90f1407d94d7b5b7263b2011fc.png)
将信将疑的我再次开启探索之旅,这时候我使用 ManagementFactory.getGarbageCollectorMXBeans() 把具体的回收器打印出来看下不就可以了吗?详细代码如下
import?java.lang.management.GarbageCollectorMXBean;
import?java.lang.management.ManagementFactory;
import?java.util.List;
public?class?GcCollectorPrinter?{
public?static?void?main(String[]?args)?{
List<GarbageCollectorMXBean>?beans?=?ManagementFactory.getGarbageCollectorMXBeans();
for?(GarbageCollectorMXBean?bean?:?beans)?{
System.out.println(bean.getName());
}
}
}
直接运行输出内容如下
PS Scavenge
PS MarkSweep
这意思是 PS MarkSweep 是 Serial Old 的意思对吗?那么 -XX:+UseParallelOldGC 打印出来的结果又是什么呢?我配置好参数再次运行如下两个命令
javac?GcCollectorPrinter.java?
java?-XX:+UseParallelOldGC?GcCollectorPrinter
如下是打印结果
PS?Scavenge
PS?MarkSweep
等等,我更加疑惑了?-XX:+UseParallelOldGC 和 -XX:+UseParallelGC 的输出结果都是 PS MarkSweep,那么他究竟是 Serial Old 还是 Parallel Old?这时候我有两个猜想
PS MarkSweep 只是回收器的别名,他可以指代 Serial Old 和 Parallel Old,毕竟他们的实现基本一样。
-XX:+UseParallelGC 和 -XX:+UseParallelOldGC 结果一样,都是用的 Parallel Old
好的那么接下来开启 GC 之旅,这个"别名"一样没办法了,我直接打印一下 GC 的日志,看下日志里面显示什么,-XX:+PrintGCDetails 这个参数就上场了,他可以输出 GC 详细的分区分析,我们再次运行刚才的两个例子如下
java?-XX:+UseParallelOldGC?-XX:+PrintGCDetails?GcCollectorPrinter
java?-XX:+PrintGCDetails?GcCollectorPrinter
结果惊人的一致
PS Scavenge
PS MarkSweep
Heap
PSYoungGen total 76288K, used 3932K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)
eden space 65536K, 6% used [0x000000076ab00000,0x000000076aed7240,0x000000076eb00000)
from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)
to space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)
ParOldGen total 175104K, used 0K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000)
object space 175104K, 0% used [0x00000006c0000000,0x00000006c0000000,0x00000006cab00000)
Metaspace
used 2729K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 297K, capacity 386K, committed 512K, reserved 1048576K
可以看到 老年代都是用的 ParOldGen 那么一点可以断定了,-XX:+UseParallelGC 和 -XX:+UseParallelOldGC 结果一样,都是用的 Parallel Old。
那么我们继续验证第二个疑问,PS MarkSweep 只是回收器的别名,他可以指代 Serial Old 和 Parallel Old,可以直接使用如下命令验证,我用的不是+而是-,这样就一定强制去掉了 Parallel Old 收集器,我们看下效果
java?-XX:-UseParallelOldGC?-XX:+PrintGCDetails?GcCollectorPrinter
PS Scavenge
PS MarkSweep
Heap
PSYoungGen total 76288K, used 3932K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)
eden space 65536K, 6% used [0x000000076ab00000,0x000000076aed7240,0x000000076eb00000)
评论