JVM的很多参数命名很有迷惑性,-XX:+UseParallel-XX:+UseParallelOldGC-XX:+UseParNewGC-XX:+UseConcMarkSweepGC咋一看容易混淆,而且JDK升个级某个GC就可能不见了,为了详细了解这些参数的区别,先来看看到底都有哪些类型的GC:

// hotspot\share\gc\shared\gc_globals.hpp
product(bool, UseConcMarkSweepGC, false,
"Use Concurrent Mark-Sweep GC in the old generation")
product(bool, UseSerialGC, false,
"Use the Serial garbage collector")
product(bool, UseG1GC, false,
"Use the Garbage-First garbage collector")
product(bool, UseParallelGC, false,
"Use the Parallel Scavenge garbage collector")
product(bool, UseParallelOldGC, false,
"Use the Parallel Old garbage collector")
experimental(bool, UseEpsilonGC, false,
"Use the Epsilon (no-op) garbage collector")
experimental(bool, UseZGC, false,
"Use the Z garbage collector")

好消息是ParNewGCJDK9中弃用了,JDK10中已经完全移除了,它的理想代替物是G1GC。然后openjdk12中现存的GC有:

  • ConcMarkSweepGC
  • SerialGC
  • G1GC
  • ParallelGC
  • EpsilonGC
  • ZGC
  • ShenandoahGC ( OpenJDK12上游的新GC,我的源码拉的早,就没有它了)

它们在源码中都有对应的独立目录:

λ tree .
├─gc
│ ├─cms # UseConcMarkSweepGC
│ ├─epsilon # UseEpsilonGC
│ ├─g1 # UseG1GC
│ ├─parallel # UseParallelGC && UseParallelOldGC
│ ├─serial # UseSerialGC
│ ├─shared # 所有GC共享的代码
│ └─z # UseZGC

本文将要简要分析Parallel GC和ParallelOld GC的区别。

要想找不同很简单:对着源码目录搜索一下UseParallelGC/UseParallelOldGC标志,可以得到所有源码的引用,而且找出来的结果通常是两者伴随出现的,看来方法是没问题的。重点关注几个地方,parallelArgument.cpp它会负责GC早期的参数处理(可以参见EpsilonGC示例):

// hotspot\share\gc\parallel\parallelArguments.cpp
void ParallelArguments::initialize() {
GCArguments::initialize();
assert(UseParallelGC || UseParallelOldGC, "Error");
// Enable ParallelOld unless it was explicitly disabled (cmd line or rc file).
if (FLAG_IS_DEFAULT(UseParallelOldGC)) {
FLAG_SET_DEFAULT(UseParallelOldGC, true);
}
FLAG_SET_DEFAULT(UseParallelGC, true);
...
}

这段代码告诉我们,除非显式指定-XX:-UseParallelOldGC,否则都开启Parallel Old。第二个地方是GCConfiguration:

// hotspot\share\gc\shared\gcConfiguration.cpp
GCName GCConfiguration::young_collector() const {
if (UseG1GC) {
return G1New;
}
// 如果开启UseParallelGC则新年代使用ParallelScavenge
if (UseParallelGC) {
return ParallelScavenge;
} if (UseConcMarkSweepGC) {
return ParNew;
} if (UseZGC) {
return NA;
} return DefNew;
} GCName GCConfiguration::old_collector() const {
if (UseG1GC) {
return G1Old;
} if (UseConcMarkSweepGC) {
return ConcurrentMarkSweep;
}
// 如果开启UseParallelOldGC则老年代使用ParallelOld,否则使用SerialOld
if (UseParallelOldGC) {
return ParallelOld;
} if (UseZGC) {
return Z;
} return SerialOld;
}

通过简单的字符串搜索就能知道:

  • +UseParallelGC = 新生代ParallelScavenge + 老年代ParallelOld
  • +UseParallelOldGC = 同上
  • -UseParallelOldGC = 新生代ParallelScavenge + 老年代SerialOld

ParallelOld和SerialOld字面上意思是老年代并行处理和老年代串行处理,关于这两个的区别也可以通过字符串搜索一窥究竟:

//hotspot\share\gc\parallel\parallelScavengeHeap.cpp
void ParallelScavengeHeap::do_full_collection(bool clear_all_soft_refs) {
if (UseParallelOldGC) {
bool maximum_compaction = clear_all_soft_refs;
// ParallelOld使用PSParallelCompact做full gc
PSParallelCompact::invoke(maximum_compaction);
} else {
// 关闭ParallelOld则使用PSMarkSweep做full gc
PSMarkSweepProxy::invoke(clear_all_soft_refs);
}
}

PSMarkSweepProxy是一个命名空间,它做的唯一一件事情就是把调用转发到PSMarkSweep类的同名方法,比如PSMarkSweepProxy::do_a()实际调用的是PSMarkSweep::do_a()。PSMarkSweep和Serial GC Full GC提到的算法几乎一样,都是串行地分四个阶段对老年代做标记-压缩,稍有不同的是PSMarkSweep支持UseAdaptiveSizePolicy参数,它可以自适应的调整新生代和老年代的大小。

总的来说,Parallel GC和Parallel Old GC说的是不一样的事情,前者表示并行分代式垃圾回收器,其老年代和新生代都是多线程并行操作。而后者只是老年代是否使用并行的一个选项(默认开启),如果关闭则老年代退化为串行操作。之所以这样是因为早期HotSpot的并行GC只支持新生代并行,老年代的并行是后面版本加入的。

最后,附上所有垃圾回收器名和对应的分代名:

垃圾回收器 新生代名 老年代名
G1GC G1New G1Old
Parallel GC ParallelScavenge ParallelOld(-UseParallelOld则是SerialOld)
CMS ParNew ConcurrentMarkSweep
Serial GC DefNew SerialOld
Epsilon N/A N/A
ZGC N/A Z
Shenandoah N/A Shenandoah

[Inside HotSpot] UseParallelGC和UseParallelOldGC的区别的更多相关文章

  1. [Inside HotSpot] C1编译器HIR的构造

    1. 简介 这篇文章可以说是Christian Wimmer硕士论文Linear Scan Register Allocation for the Java HotSpot™ Client Compi ...

  2. [Inside HotSpot] C1编译器优化:全局值编号(GVN)

    1. 值编号 我们知道C1内部使用的是一种图结构的HIR,它由基本块构成一个图,然后每个基本块里面是SSA形式的指令,关于这点如可以参考[Inside HotSpot] C1编译器工作流程及中间表示. ...

  3. [Inside HotSpot] C1编译器优化:条件表达式消除

    1. 条件传送指令 日常编程中有很多根据某个条件对变量赋不同值这样的模式,比如: int cmov(int num) { int result = 10; if(num<10){ result ...

  4. [inside hotspot] 汇编模板解释器(Template Interpreter)和字节码执行

    [inside hotspot] 汇编模板解释器(Template Interpreter)和字节码执行 1.模板解释器 hotspot解释器模块(hotspot\src\share\vm\inter ...

  5. [Inside HotSpot] Java分代堆

    [Inside HotSpot] Java分代堆 1. 宇宙初始化 JVM在启动的时候会初始化各种结构,比如模板解释器,类加载器,当然也包括这篇文章的主题,Java堆.在hotspot源码结构中gc/ ...

  6. [Inside HotSpot] 模板解释器

    0. 简介 众所周知,hotspot默认使用解释+编译混合(-Xmixed)的方式执行代码.它首先使用模板解释器对字节码进行解释,当发现一段代码是热点的时候,就使用C1/C2 JIT进行优化编译再执行 ...

  7. [Inside HotSpot] C1编译器工作流程及中间表示

    1. C1编译器线程 C1编译器(aka Client Compiler)的代码位于hotspot\share\c1.C1编译线程(C1 CompilerThread)会阻塞在任务队列,当发现队列有编 ...

  8. [Inside HotSpot] Java的方法调用

    1. 方法调用模块入口 Java所有的方法调用都会经过JavaCalls模块.该模块又细分为call_virtual调用虚函数,call_static调用静态函数等.虚函数调用会根据对象类型进行方法决 ...

  9. [Inside HotSpot] hotspot的启动流程与main方法调用

    hotspot的启动流程与main方法调用 虚拟机的使命就是执行public static void main(String[])方法,从虚拟机创建到main方法执行会经过一系列流程.这篇文章详细讨论 ...

随机推荐

  1. 移动端H5前端性能优化指南:

    分享地址:https://isux.tencent.com/h5-performance.html

  2. statistics-skewed data

    参考文献: http://www.statisticshowto.com/skewed-distribution/ left/negatively-skewed distributions : box ...

  3. k短路模板

    https://acm.taifua.com/archives/jsk31445.html 链接: https://nanti.jisuanke.com/t/31445 #include <io ...

  4. 如何提高UDP的可靠性

    TCP是通过确认机制和超时重传机制实现可靠传输 UDP UDP它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频.视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数 ...

  5. B - CD UVA - 624

    https://cn.vjudge.net/contest/224070#problem/B #include <iostream> #include <cstring> #i ...

  6. Leetcode 145. 二叉树的后序遍历

    题目链接 https://leetcode-cn.com/problems/binary-tree-postorder-traversal/description/ 题目描述 给定一个二叉树,返回它的 ...

  7. 【Jenskins】安装与配置

    Jenskins教程:http://www.yiibai.com/jenkins/ 一.Jenskins的安装 1.jenskins下载和启动 Jenskins下载地址:https://jenkins ...

  8. kNN的维数灾难与PCA降维

    主成分分析 PCA 协方差矩阵 假设我们有 \[ X = \begin{pmatrix}X_1\\X_2\\\vdots\\X_m\end{pmatrix}\in\mathbb{R}^{m\times ...

  9. oracle无参数和带参数的存储过程实例

    SQL中调用存储过程语句:call procedure_name(); 注:调用时”()”是不可少的,无论是有参数还是无参数. 定义对数据库存储过程的调用时1.无参数存储过程:{call proced ...

  10. 【Istio】error initializing configuration '/etc/istio/proxy/envoy-rev0.json': malformed IP address: istio-statsd-prom-bridge

    今天遇到一个问题,istio的组件一直在重启,查看log大概是这个样子 --03T07::.935580Z info Epoch starting --03T07::.936317Z info Env ...