JDK 8 到底默认用的是哪款 GC 收集器?

为啥是 JDK8?不是 9 也不是 10?因为 JDK8 还是市场占有率最高的,所以针对这个版本我做了深入的探索。

《深入理解 Java 虚拟机》第三版第 128 页中提到 JDK 9 之前,Server 默认使用 Parallel Scavenge + Serial Old(PS MarkSweep),那么真的是这样的吗? 我带着这个疑问做了如下验证

  1. 直接使用命令查看一下当前 JVM 默认参数

java -XX:+PrintCommandLineFlags -version

输入内容如下

-XX:InitialHeapSize=268435456
-XX:MaxHeapSize=4294967296
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-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

那么这里再详细科普一下,下面是每个参数对应的回收器的类型

将信将疑的我再次开启探索之旅,这时候我使用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 MarkSweepSerial Old的意思对吗?那么-XX:+UseParallelOldGC打印出来的结果又是什么呢?我配置好参数再次运行如下两个命令

javac GcCollectorPrinter.java
java -XX:+UseParallelOldGC GcCollectorPrinter

如下是打印结果

PS Scavenge
PS MarkSweep

等等,我更加疑惑了?-XX:+UseParallelOldGC和  -XX:+UseParallelGC的输出结果都是PS MarkSweep,那么他究竟是Serial Old还是Parallel Old
这时候我有两个猜想

  1. PS MarkSweep只是回收器的别名,他可以指代Serial OldParallel Old,毕竟他们的实现基本一样。

  2. -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 OldParallel 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)
from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)
to space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)
PSOldGen total 175104K, used 0K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000)
object space 175104K, 0% used [0x00000006c0000000,0x00000006c0000000,0x00000006cab00000)
Metaspace used 2728K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 297K, capacity 386K, committed 512K, reserved 1048576K

唯一的变化就是ParOldGen换成了PSOldGen,经过查询我们可以确定PSOldGen就是  Serial Old所以终于有了答案。

  1. PS MarkSweep只是回收器的别名,他可以指代Serial OldParallel Old

  2. -XX:+UseParallelGC-XX:+UseParallelOldGC结果一样,都是用的Parallel Old

那书上说的还能有假?保险起见还是去找一些资料吧

在 JDK 8 的官网找到了一些蛛丝马迹
链接:https://urlify.cn/67NnEz

Parallel compaction is enabled by default if the option -XX:+UseParallelGC has been specified. The option to turn it off is -XX:-UseParallelOldGC.

大致意思就是说-XX:+UseParallelGC就会开始Parallel收集器除非手动关闭,那么可是书上为什么说是Serial呢?

终于我在 JDK 源码 commit 记录里面找到了答案,在 JDK 7U4 之前确实 UserParallelGC 用的就是 Serial,在这个版本之后 Parallel 已经很成熟了,所以直接替换了旧的收集器,所以 JDK 7u4 以后的 7 和 JDK 8 老年代默认使用的都是 Parallel 收集器,只是书中没有更新这个细节。
网址:
https://bugs.openjdk.java.net/browse/JDK-6679764
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/rev/24cae3e4cbaa
原文:

Server-class machine ergonomics was introduced in jdk5. If the machine upon which
the jvm is running is powerful enough (currently, at least 2 physical cores plus
at least 2gb of memory), the server jvm is invoked using the parallel scavenger
rather than the serial scavenger. Currently the old gen collector used is
serial mark-sweep-compact. Now that the parallel old gen collector is mature,
we should change to using it instead.
Issue Links

研究了 2 天,终于知道 JDK 8 默认 GC 收集器了!相关推荐

  1. 从JDK 8到JDK 17,GC都有哪些进步?

    作者 | Stefan Johansson 译者 | 弯月 出品 | CSDN(ID:CSDNnews) JDK17 发布已经几个月了,其中不仅包含很多新语言功能,而且与旧版 JDK 相比,性能提升也 ...

  2. jdk 流合并_JDK 12,合并的收集器和命名的挑战

    jdk 流合并 看来可能是一种新的方法,将可在java.util.streams.Collectors类JDK 12即会,根据新方法的提出了基于Javadoc的文档,"返回一个收藏家是将输入 ...

  3. JDK 12,合并的收集器和命名的挑战

    看来可能是一种新的方法,将可在java.util.streams.Collectors类JDK 12即会,根据新方法的提出了基于Javadoc的文档,"返回一个收藏家是将输入的元素两个规定的 ...

  4. 通过JDK动态代理实现拦截器

    拦截器 拦截器是我们开发中接触比较多的.今天使用JDK动态代理模式来实现拦截器.实现过程我们通过代码来展示,代码中有相应的解释: //拦截器接口 public interface Intercepto ...

  5. Linux安装jdk替换默认open jdk

    上传安装包到Linux中,切换到/usr/local目录下创建一个java目录 cd /usr/local mkdir java 解压jdk压缩包到目录中 tar -zxvf jdk-8u171-li ...

  6. JDK默认GC算法是个谜

    JDK默认GC算法是个谜 背景 我们系统采用openjdk:8u212-b04-jdk-stretch作为基础镜像,java -version命令输出: openjdk version "1 ...

  7. Oracle慌了!华为终于对JDK下手了!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:网络 整理:公众号-码出未来 近日有开发者在华为 o ...

  8. 研究了半天,终于把数字孪生内涵搞清楚了 by 傅一平

    数字孪生很火,自己却不以为然,因为一方面觉得数据工作者干的活跟数字孪生差不多,不就是业务数据化和数据业务化吗?二是别人来谈数字孪生的时候,除了3D建模就讲不出实质性的东西了,自己就在想,这又能解决我的 ...

  9. 研究一天,终于把MyBatis的一级缓存和二级缓存搞清楚了

    介绍 MyBatis 现在是面试必问的,其中最主要的除了一些启动流程,基础语法,那么就是缓存问题了. 大家都知道 MyBatis 是有二级缓存,底层都是用HashMap实现的,key为CacheKey ...

最新文章

  1. python爬boss网站_python之requests爬虫Boss数据
  2. apple手表android手机,Apple Watch 4发布了,安卓手机用户如何选择呢?
  3. 引入ui组件_Vuejs, Semantic CSS前端框架fish-ui
  4. Day3-php 字符串1
  5. Google “推翻”无监督研究成果!斩获 ICML 2019 最佳论文
  6. 7-4 用天平找小球 (10 分)
  7. 51单片机三种烧录的方法介绍
  8. editplus使用php,EditPlus如何运行php文件
  9. 集群资源管理与任务调度系统综述
  10. 参与者模式(Actor model)
  11. 计算机三级网络技术知识考点
  12. keepass使用坚果云同步
  13. mzy对于枚举的理解
  14. 【css】鼠标禁用样式
  15. 笔记本电脑重装win10系统图文并茂详细操作教程(微PE工具箱重装系统)
  16. 如何远程唤醒(WOL)主板为技嘉(gigabyte)的B85M-D3H的linux主机
  17. 文章引言--森林干扰--rse
  18. 魅蓝u20android版本,魅族魅蓝U20刷机包 Flyme 6 稳定版系统发布 性能提升 超长待机 全面优化...
  19. Ubuntu18.04安装opencv3.4.1和opencv_contrib3.4.1时遇到错误处理方法
  20. html文本框颜色填充颜色设置,文本框填充色怎么设置

热门文章

  1. 新的一年,请以这样的标准完善自我
  2. 浅谈尾递归的优化方式
  3. Ubuntu启用休眠hibernate
  4. 06_Dart异常处理
  5. 安装中文语言包会导致 Troubleshoot Compatibility 失败
  6. tp3.2.3运用phpexcel将excel文件导入mysql数据库
  7. 03-spring_配置bean
  8. sscanf函数中类型不匹配警告引发的BUG和思考
  9. 修改代码的艺术----- 2.2 高层测试 2.3 测试覆盖
  10. 转载一篇开源http服务器(C语言)