1、cms垃圾回收算法在gc过程中哪几个阶段会暂停应用县城
中间调整过几次,先搞了几台机器做了验证,后来逐步推广的。
1、调大heap区,由原来的4g,调整到5g,young区的大小不变,还是2g,这时候old区就由2g变为3g了(这样保证old区有足够的空间);
2、设置-XX:UseCMSInitiatingOccupancyOnly,其实这个不关这个问题,只是发现半夜CMS进行的有点频繁,就禁止掉了悲观策略;
3、设置CMS区回收的比例,从80%调整到75%,让old区尽早的进行,有足够的空间剩余;
为什么要有GC(垃圾回收)?
JVM通过GC来回收堆和方法区中的内存,GC的基本原理就是找到程序中不再被使用的对象,然后回收掉这些对象占用的内存。
主要的收集器有哪些?
引用计数器和跟踪计数器两种。
引用计数器记录对象是否被引用,当计数器为零时,说明对象已经不再被使用,可以进行回收。java中的对象有复杂的引用关系,不是很适合引用计数器,所以sun jdk中并没有实现这种GC方式。
跟踪收集器,全局记录数据的引用状态,基于一定的条件触发。执行的时候,从根集合开始扫描对象的引用关系,主要有复制(copying)、标记-清除(Mark-Sweep)、标记-压缩(Mark-Compact)那种算法。
2、elasticsearch java 怎么设置 ignore
今天,事情终于发生了。Java6(Mustang),是2006年早些时候出来的,至今仍然应用在众多生产环境中,现在终于走到了尽头。已经没有什么理由阻止迁移到Java7(Dolphin)上了。
这也促使我想写一篇关于在ElasticSearch上配置Java6和7的细微差异的博文。
Elasticsearch对Java虚拟机进行了预先的配置。通常情况下,因为这些配置的选择还是很谨慎的,所以你不需要太关心,并且你能立刻使用ElasticSearch。
但是,当你监视ElasticSearch节点内存时,你可能尝试修改一些配置。这些修改是否会改善你的处境?
这篇博文尝试揭开Elasticsearch配置的神秘面纱,并且讨论最常见的调整。最终,会给出一些推荐的配置调整。
Elasticsearch JVM 配置概览:
这些是Elasticsearch 0.19.11版本的默认配置。
JVM参数 Elasticsearch默认值 Environment变量
-Xms 256m ES_MIN_MEM
-Xmx 1g ES_MAX_MEM
-Xms and -Xmx ES_HEAP_SIZE
-Xmn ES_HEAP_NEWSIZE
-XX:MaxDirectMemorySize ES_DIRECT_SIZE
-Xss 256k
-XX:UseParNewGC +
-XX:UseConcMarkSweepGC +
-XX: 75
-XX:UseCMSInitiatingOccupancyOnly +
-XX:UseCondCardMark (commented out)
首先你注意到的是,Elasticsearch预留了256M到1GB的堆内存。
这个设置适用于开发和演示环境。开发人员只需要简单的解压发行包,再执行./bin/elasticsearch -f就完成了Elasticsearch的安装。当然这点对于开发来说非常棒,并且在很多场景下都能工作,但是当你需要更多内存来降低Elasticsearch负载的时候就不行了,你需要比2GB RAM更多的可用内存。
ES_MIN_MEM/ES_MAX_MEM是控制堆大小的配置。新的ES_HEAP_SIZE变量是一个更为便利的选择,因为将堆的初始大小和最大值设为相同。也推荐在分配堆内存时尽可能不要用内存的碎片。内存碎片对于性能优化来说非常不利。
ES_HEAP_NEWSIZE是可选参数,它控制堆的子集大小,也就是新生代的大小。
ES_DIRECT_SIZE控制本机直接内存大小,即JVM管理NIO框架中使用的数据区域大小。本机直接内存可以被映射到虚拟地址空间上,这样在64位的机器上更高效,因为可以规避文件系统缓冲。Elasticsearch对本机直接内存没有限制(可能导致OOM)。
由于历史原因Java虚拟机有多个垃圾收集器。可以通过以下的JVM参数组合启用:
JVM parameter Garbage collector
-XX:+UseSerialGC serial collector
-XX:+UseParallelGC parallel collector
-XX:+UseParallelOldGC Parallel compacting collector
-XX:+UseConcMarkSweepGC Concurrent-Mark-Sweep (CMS) collector
-XX:+UseG1GC Garbage-First collector (G1)
UseParNewGC和UseConcMarkSweepGC组合启用垃圾收集器的并发多线程模式。UseConcMarkSweepGC自动选择UseParNewGC模式并禁用串行收集器(Serial collector)。在Java6中这是默认行为。
提炼了一种CMS(Concurrent-Mark-Sweep)垃圾收集设置;它将旧生代触发垃圾收集的阀值设为75.旧生代的大小是堆大小减去新生代大小。这告诉JVM当堆内容达到75%时启用垃圾收集。这是个估计的值,因为越小的堆可能需要越早启动GC。
UseCondCardMark将在垃圾收集器的card table使用时,在marking之前进行额外的判断,避免冗余的store操作。UseCondCardMark不影响Garbage-First收集器。强烈推荐在高并发场景下配置这个参数(规避card table marking技术在高并发场景下的降低吞吐量的负面作用)。在ElasticSearch中,这个参数是被注释掉的。
有些配置可以参考诸如Apache Cassandra项目,他们在JVM上有类似的需求。
总而言之,ElastciSearch配置上推荐:
1. 不采用自动的堆内存配置,将堆大小默认最大值设为1GB
2.调整触发垃圾收集的阀值,比如将gc设为75%堆大小的时候触发,这样不会影响性能。
3.禁用Java7默认的G1收集器,前提是你的ElasticSearch跑在Java7u4以上的版本上。
JVM进程的内存结果
JVM内存由几部分组成:
Java代码本身:包括内部代码、数据、接口,调试和监控代理或者字节码指令
非堆内存:用于加载类
栈内存:用于为每个线程存储本地变量和操作数
堆内存:用于存放对象引用和对象本身
直接缓冲区:用于缓冲I/O数据
堆内存的大小设置非常重要,因为Java的运行依赖于合理的堆大小,并且JVM需要从操作系统那获取有限的堆内存,用于支撑整个JVM生命周期。
如果堆太小,垃圾回收就会频繁发生,发生OOM的几率会很大。
如果堆太大,垃圾回收会延迟,但是一旦回收,就需要处理大量的存活堆数据。并且,操作系统的压力也会变大,因为JVM进程需要更大的堆,产生换页的可能性就会提高。
注意,使用CMS垃圾收集器,Java不会把内存还给操作系统,因此配置合理的堆初始值和最大值就非常重要。
非堆内存由Java应用自动分配。没有什么参数控制这里的大小,这是由Java应用程序代码自己决定的。
栈内存在每个线程中分配,在Elasticsearch中,每个线程大小必须由128K增加到256K,因为Java7比Java6需要更大的栈内存 ,这是由于Java7支持新的编程语言特征来利用栈空间。比如,引入了continuations模型,编程语言的一个著名概念。Continuations模型对于
协同程序、绿色线程(green thread)、纤程(fiber)非常有用 。当实现非阻塞I/O时,一个大的优势是,代码可以根据线程实际使用情况编写,但是运行时仍然在后台采用非阻塞I/O。Elasticsearch使用了多个线程池,因为Netty I/O框架和Guava是Elasticsearch的基础组件,因此在用Java7时,可以考虑进一步挖掘优化线程的特性。
发挥增加栈空间大小的优势还是有挑战的,因为不同的操作系统、不同的CPU架构,甚至在不同的JVM版本之间,栈空间的消耗不是容易比较的。取决于CPU架构和操作系统,JVM的栈空间大小是内建的。他们是否在所有场景下都适合?例如Sloaris Sparc 64位的JVM Xss默认为512K,因为有更大地址指针,Sloaris X86为320K。Linux降为256K。Windows 32位Java6默认320K,Windows 64位则为1024K。
大堆的挑战
今天,几GB的内存是很常见的。但是在不久以前,系统管理员还在为多几G的内存需求泪流满面。
Java垃圾收集器是随着2006年的Java6的出现而显著改进的。从那以后,可以并发执行多任务,并且减少了GC停顿几率: stop - the - world阶段。CMS算法是革命性的,多任务,并发, 不需要移动的GC。但是不幸的是,对于堆的存活数据量来说,它是不可扩展的。Prateek Khanna 和 Aaron Morton给出了CMS垃圾收集器能够处理的堆规模的数字。
避免Stop-the-world阶段
我们已经学习了Elasticsearch如何配置CMS垃圾收集器。但这并不能组织长时间的GC停顿,它只是降低了发生的几率。CMS是一个低停顿几率的收集器,但是仍然有一些边界情况。当堆上有MB级别的大数组,或者其他一些特殊的场景,CMS可能比预期要花费更多的时间。
MB级别数组的创建在Lucene segment-based索引合并时是很常见的。如果你希望降低CMS的额外负载,就需要调整Lucene合并阶段的段数量,使用参数index.merge.policy.segments_per_tier
减少换页
大堆的风险在于内存压力上。注意,如果Java JVM在处理大堆时,这部分内存对于系统其它部分来说是不可用的。如果内存吃紧,操作系统会进行换页,并且,在紧急情况下,当所有其他方式回收内存都失败时,会强制杀掉进程。如果换页发生,整个系统的性能会下降,自然GC的性能也跟着下降。所以,不要给堆分配太多的内存。
垃圾收集器的选择
从Java JDK 7u4开始,Garbage-First(G1)收集器是Java7默认的垃圾收集器。它适用于多核的机器以及大内存。它一方面降低了停顿时间,另一方面增加了停顿的次数。整个堆的操作,例如全局标记,是在应用线程中并发执行的。这会防止随着堆或存活数据大小的变化,中断时间也成比例的变化。
G1收集器目标是获取更高的吞吐量,而不是速度。在以下情况下,它能运行的很好:
1. 存活数据占用了超过50%的Java堆
2. 对象分配比例或者promotion会有明显的变化
3. 不希望gc或者compaction停顿时间长(超过0.5至1s)
注意,如果使用G1垃圾收集器,堆不再使用的内存可能会被归还给操作系统
G1垃圾收集器的不足是CPU使用率越高,应用性能越差。因此,如果在内存足够和CPU能力一般的情况下,CMS可能更胜一筹。
对于Elasticsearch来说,G1意味着没有长时间的stop-the-world阶段,以及更灵活的内存管理,因为buffer memory和系统I/O缓存能更充分的利用机器内存资源。代价就是小成本的最大化性能,因为G1利用了更多CPU资源。
性能调优策略
你读这篇博文因为你希望在性能调优上得到一些启示:
1. 清楚了解你的性能目标。你希望最大化速度,还是最大化吞吐量?
2. 记录任何事情(log everything),收集统计数据,阅读日志、分析事件来诊断配置
3. 选择你调整的目标(最大化性能还是最大化吞吐量)
4. 计划你的调整
5. 应用你的新配置
6. 监控新配置后的系统
7. 如果新配置没有改善你的处境,重复上面的一系列动作,反复尝试
Elasticsearch垃圾收集日志格式
Elasticsearch长时间GC下warns级别的日志如下所示:
[2012-11-26 18:13:53,166][WARN ][monitor.jvm ] [Ectokid] [gc][ParNew][1135087][11248] ration [2.6m], collections [1]/[2.7m], total [2.6m]/[6.8m], memory [2.4gb]->[2.3gb]/[3.8gb], all_pools {[Code Cache] [13.7mb]->[13.7mb]/[48mb]}{[Par Eden Space] [109.6mb]->[15.4mb]/[1gb]}{[Par Survivor Space] [136.5mb]->[0b]/[136.5mb]}{[CMS Old Gen] [2.1gb]->[2.3gb]/[2.6gb]}{[CMS Perm Gen] [35.1mb]->[34.9mb]/[82mb]}
JvmMonitorService类中有相关的使用方式:
Logfile Explanation
gc 运行中的gc
ParNew new parallel garbage collector
ration 2.6m gc时间为2.6分钟
collections [1]/[2.7m] 在跑一个收集,共花2.7分钟
memory [2.4gb]->[2.3gb]/[3.8gb] 内存消耗, 开始是2.4gb, 现在是2.3gb, 共有3.8gb内存
Code Cache [13.7mb]->[13.7mb]/[48mb] code cache占用内存
Par Eden Space [109.6mb]->[15.4mb]/[1gb] Par Eden Space占用内存
Par Survivor Space [136.5mb]->[0b]/[136.5mb] Par Survivor Space占用内存
CMS Old Gen [2.1gb]->[2.3gb]/[2.6gb] CMS Old Gen占用内存
CMS Perm Gen [35.1mb]->[34.9mb]/[82mb] CMS Perm Gen占用内存
JvmMonitorSer
一些建议
1. 不要在Java 6u22之前的发布版本中跑Elasticsearch。有内存方面的bug。那些超过两三年的bug和缺陷会妨碍Elasticsearch的正常运行。与旧的OpenJDK 6相比,更推荐Sun/Oracle的版本,因为后者修复了很多bug。
2. 放弃Java6,转到Java7。Oracle宣称Java6更新到2013年2月结束。考虑到Elasticsearch还是一个相对新的软件,应该使用更新的技术来提升性能。尽量从JVM中挤压性能。检查操作系统的版本。在最新版本的操作系统中运行,有助于你的Java运行环境达到最佳性能。
3. 定期更新Java运行环境。平均一个季度一次。告诉sa你需要及时更新Java版本,以获取Java性能的提升。
4. 从小到大。先在Elasticsearch单节点上进行开发。但是不要忘了Elasticsearch分布式的强大功能。单节点不能模拟生产环境的特征,至少需要3个节点进行开发测试。
5. 在调整JVM之前先做一下性能测试。对你的系统建立性能基线。调整测试时候的节点数量。如果索引时候负载很高,你可能需要降低Elasticsearch索引时候占用的堆大小,通过index.merge.policy.segments_per_tierparameter参数调整段的合并。
6. 调整前清楚你的性能目标,然后决定是调整速度还是吞吐量。
7. 启用日志以便更好的进行诊断。在优化系统前进行小心的评估。
8. 如果使用CMS垃圾收集器,你可能需要加上合理的 -XX:CMSWaitDuration 参数。
9. 如果你的堆超过6-8GB,超过了CMS垃圾收集器设计容量,你会遇到长时间的stop-the-world阶段,你有几个方案:调整参数降低长时间GC的几率减少最大堆的大小;启用G1垃圾收集器。
10. 学习垃圾收集调优艺术。如果你想精通的话,列出可用的JVM选项,在java命令中加入java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version,然后调优。
3、如何指定定java cms垃圾回收
如果你的JAVA应用程序有以下几个特点,那么可以使用Concurrent Mark Sweep (CMS) 垃圾收集器。
希望JAVA垃圾回收器回收垃圾的时间尽可能短;
应用运行在多CPU的机器上,有足够的CPU资源;
有比较多生命周期长的对象;
希望应用的响应时间短。
4、cms垃圾回收算法在gc过程哪几个阶段会暂停应用线程
?
5、java虚拟机常见的几种垃圾收集算法
1、垃圾收集器概述
垃圾收集器是垃圾回收算法(标记-清除算法、复制算法、标记-整理算法、火车算法)的具体实现,不同商家、不同版本的JVM所提供的垃圾收集器可能会有很在差别,本文主要介绍HotSpot虚拟机中的垃圾收集器。
1-1、垃圾收集器组合
JDK7/8后,HotSpot虚拟机所有收集器及组合(连线),如下图:
(A)、图中展示了7种不同分代的收集器:
Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;
(B)、而它们所处区域,则表明其是属于新生代收集器还是老年代收集器:
新生代收集器:Serial、ParNew、Parallel Scavenge;
老年代收集器:Serial Old、Parallel Old、CMS;
整堆收集器:G1;
(C)、两个收集器间有连线,表明它们可以搭配使用:
Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1;
(D)、其中Serial Old作为CMS出现"Concurrent Mode Failure"失败的后备预案(后面介绍);
1-2、并发垃圾收集和并行垃圾收集的区别
(A)、并行(Parallel)
指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态;
如ParNew、Parallel Scavenge、Parallel Old;
(B)、并发(Concurrent)
指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行);
用户程序在继续运行,而垃圾收集程序线程运行于另一个CPU上;
如CMS、G1(也有并行);
1-3、Minor GC和Full GC的区别
(A)、Minor GC
又称新生代GC,指发生在新生代的垃圾收集动作;
因为Java对象大多是朝生夕灭,所以Minor GC非常频繁,一般回收速度也比较快;
(B)、Full GC
又称Major GC或老年代GC,指发生在老年代的GC;
出现Full GC经常会伴随至少一次的Minor GC(不是绝对,Parallel Sacvenge收集器就可以选择设置Major GC策略);
Major GC速度一般比Minor GC慢10倍以上;
6、JVM的垃圾算法有哪几种
一、垃圾收集器概述
如上图所示,垃圾回收算法一共有7个,3个属于年轻代、三个属于年老代,G1属于横跨年轻代和年老代的算法。
JVM会从年轻代和年老代各选出一个算法进行组合,连线表示哪些算法可以组合使用
二、各个垃圾收集器说明
1、Serial(年轻代)
年轻代收集器,可以和Serial Old、CMS组合使用
采用复制算法
使用单线程进行垃圾回收,回收时会导致Stop The World,用户进程停止
client模式年轻代默认算法
GC日志关键字:DefNew(Default New Generation)
图示(Serial+Serial Old)
2、ParNew(年轻代)
新生代收集器,可以和Serial Old、CMS组合使用
采用复制算法
使用多线程进行垃圾回收,回收时会导致Stop The World,其它策略和Serial一样
server模式年轻代默认算法
使用-XX:ParallelGCthreads参数来限制垃圾回收的线程数
GC日志关键字:ParNew(Parallel New Generation)
图示(ParNew + Serail Old)
3、Paralle Scavenge(年轻代)
新生代收集器,可以和Serial Old、Parallel组合使用,不能和CMS组合使用
采用复制算法
使用多线程进行垃圾回收,回收时会导致Stop The World
关注系统吞吐量
-XX:MaxGCPauseMillis:设置大于0的毫秒数,收集器尽可能在该时间内完成垃圾回收
-XX:GCTimeRatio:大于0小于100的整数,即垃圾回收时间占总时间的比率,设置越小则希望垃圾回收所占时间越小,CPU能花更多的时间进行系统操作,提高吞吐量
-XX:UseAdaptiveSizePolicy:参数开关,启动后系统动态自适应调节各参数,如-Xmn、-XX:SurvivorRatio等参数,这是和ParNew收集器重要的区别
GC日志关键字:PSYoungGen
4、Serial Old(年老代)
年老代收集器,可以和所有的年轻代收集器组合使用(Serial收集器的年老代版本)
采用 ”标记-整理“算法,会对垃圾回收导致的内存碎片进行整理
使用单线程进行垃圾回收,回收时会导致Stop The World,用户进程停止
GC日志关键字:Tenured
图示(Serial+Serial Old)
5、Parallel Old(年老代)
年老代收集器,只能和Parallel Scavenge组合使用(Parallel Scavenge收集器的年老代版本)
采用 ”标记-整理“算法,会对垃圾回收导致的内存碎片进行整理
关注吞吐量的系统可以将Parallel Scavenge+Parallel Old组合使用
GC日志关键字:ParOldGen
图示(Parallel Scavenge+Parallel Old)
6、CMS(Concurrent Mark Sweep年老代)
年老代收集器,可以和Serial、ParNew组合使用
采用 ”标记-清除“算法,可以通过设置参数在垃圾回收时进行内存碎片的整理
1、:默认开启,FullGC时进行内存碎片整理,整理时用户进程需停止,即发生Stop The World
2、CMSFullGCsBeforeCompaction:设置执行多少次不压缩的Full GC后,执行一个带压缩的(默认为0,表示每次进入Full GC时都进行碎片整理)
CMS是并发算法,表示垃圾回收和用户进行同时进行,但是不是所有阶段都同时进行,在初始标记、重新标记阶段还是需要Stop the World。CMS垃圾回收分这四个阶段
1、初始标记(CMS Initial mark) Stop the World 仅仅标记一下GC Roots能直接关联到的对象,速度快
2、并发标记(CMS concurrent mark) 进行GC Roots Tracing,时间长,不发生用户进程停顿
3、重新标记(CMS remark) Stop the World 修正并发标记期间因用户程序继续运行导致标记变动的那一部分对象的标记记录,停顿时间较长,但远比并发标记时间短
4、并发清除(CMS concurrent sweep) 清除的同时用户进程会导致新的垃圾,时间长,不发生用户进程停顿
适合于对响应时间要求高的系统
GC日志关键字:CMS-initial-mark、CMS-concurrent-mark-start、CMS-concurrent-mark、CMS-concurrent-preclean-start、CMS-concurrent-preclean、CMS-concurrent-sweep、CMS-concurrent-reset等等
缺点
1、对CPU资源非常敏感
2、CMS收集器无法处理浮动垃圾,即清除时用户进程同时产生的垃圾,只能等到下次GC时回收
3、因为是使用“标记-清除”算法,所以会产生大量碎片
图示
7、G1
G1收集器由于没有使用过,所以从网上找了一些教程供大家了解
并行与并发
分代收集
空间整合
可预测的停顿
7、jvm的理解
JVM主要就是为java程序提供一个运行环境,包括类的加载,内存的分配,垃圾的回收,JVM将内存划分为堆,虚拟机栈,线程计数器,本地方法栈,方法区五个内存区域。
为了满足java程序运行时的垃圾回收,jvm提供了一些垃圾回收器用于堆内存的回收,常用的垃圾收集器包括ParNew新生代垃圾收集器,cms老年代垃圾收集器,G1垃圾收集器,这些垃圾收集器根据年龄代对象的特点使用不同的垃圾回收算法,为了解决垃圾收集时GC停顿对于Java程序的影响,使用一些参数的配置尽量减少垃圾回收时的停顿。
比如ParNew新生代垃圾收集器采用复制收集算法,使用多线程收集,提高垃圾回收的效率,CMS采用分段收集,对于比较耗时的阶段允许用户线程并行,但随之而来的也会导致一些缺陷,比如浮动垃圾,cpu资源紧张,内存碎片的问题,对于这些问题,可以通过JVM调优去尽量避免,比如浮动垃圾则可以减小CMS垃圾回收的老年代内存阈值。
G1垃圾收集器则采用可控的GC停顿时间来进行垃圾回收,将内存划分为一个个小的region,逻辑上划分出年轻代和老年代,所以G1垃圾收集器的调优主要就是对于GC停顿时间的调优,太大可能会导致每次GC停顿时间太长,太小可能导致GC发生的太频繁。
对于JVM调优这个话题,我们主要要保证减少YGC的次数,和尽量避免Full GC,因为对老年代的回收由于存活的对象比较多,回收是比较耗时的,那么对于这目标的实现,我们主要围绕一个思想来做,就是尽量保证每次回收后存活的对象可以存放在s区,这些都需要对程序有一个预测和平时的JVM观测
8、如何提高java虚拟机的垃圾收集器
Serial(串行GC)收集器
Serial收集器是一个新生代收集器,单线程执行,使用复制算法。它在进行垃圾收集时,必须暂停其他所有的工作线程(用户线程)。是Jvm client模式下默认的新生代收集器。对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。
ParNew(并行GC)收集器
ParNew收集器其实就是serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为与Serial收集器一样。
Parallel Scavenge(并行回收GC)收集器
Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,又是并行多线程收集器。parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而parallel Scavenge收集器的目标则是达到一个可控制的吞吐量。吞吐量= 程序运行时间/(程序运行时间 + 垃圾收集时间),虚拟机总共运行了100分钟。其中垃圾收集花掉1分钟,那吞吐量就是99%。
Serial Old(串行GC)收集器
Serial Old是Serial收集器的老年代版本,它同样使用一个单线程执行收集,使用“标记-整理”算法。主要使用在Client模式下的虚拟机。
Parallel Old(并行GC)收集器
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。