JVM学习笔记(六)垃圾收集器

 

7.4 垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。


 

7.4.1 Serial收集器

Serial 收集器是最基本、发展历史悠久的收集器。曾是(JDK1.3.1)之前新生代收集唯一的选择。

优点: 简单高效,拥有很高的单线程收集效率
缺点: 收集过程需要暂停所有线程
算法: 复制算法
适用范围: 新生代
应用: Client 模式下默认的新生代收集器

 

7.4.2 ParNew收集器

Serial收集器的多线程版本。

优点:在多CPU时,比Serial效率高。
缺点:收集过程暂停所有应用程序线程,单CPU时比Serial效率差。
算法:复制算法
适用范围:新生代
应用:运行在Server模式下的虚拟机中首选的新生代收集器

 

 

7.4.3 Parallel Scavenge收集器

Parallel Scavenge收集器 是新生代收集器,又是并行 多线程收集器,看上去和ParNew一样,Parallel Scavenge收集器更关心系统吞吐量

吞吐量=运行用户代码时间/ (运行代码时间+垃圾收集时间)

比如虚拟机运行了100分钟,垃圾收集1分钟,吞吐量=(100-1)/100=99%

吞吐量越大,意味着垃圾收集的时间段,则用户代码可以充分利用CPU资源,更快的执行程序。

应用

-XX:MaxGCPauseMillis控制最大的垃圾收集停顿时间,
-XX:GCTimeRatio直接设置吞吐量的大小。

 

7.4.4 Serial Old 收集器

Serial Old 收集器 是Serial 收集器的老年代版本,不同的是采用“标记-整理”算法,运行过程和Serial 收集器一样。

 

7.4.5 Parallel Old 收集器

Parallel Old收集器是 Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理算法”进行垃圾 回收。

关注吞吐量优先

 

7.4.6 CMS收集器

CMS (Concurrent Mark Sweep) 收集器是一种以获取 最短回收停顿时间 为目标的收集器。

采用的是“标记-清除算法”,分为四步

1)初始标记  CMS initial mark    标记GC Roots能关联的对象,STW->速度很快
2)并发标记  CMS concurrent mark 进行GC Roots Tracing
3)重新标记  CMS remark          修改并发标记因用户程序变动的内容,STW
4) 并发清除  CMS concurrent sweep

由于整个过程中,并发标记和并发清除,收集器线程和用户线程一起工作的。

所以说CMS收集器的内存回收过程是与用户线程一起并发执行的。

优点:并发收集、低停顿。

缺点:产生大量空间碎片、并发阶段会降低吞吐量。

 

7.4.7 G1收集器

特点

并行与并发
分代收集
空间整合(整体上属于“标记-整理”算法,不会导致空间碎片)
可预测的停顿(比CMS更先进的地方就是 可以指定长度M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒)

使用G1收集器时,Java堆的内存布局与其他收集器很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。

G1收集器工作过程

1)初始标记(Initial Marking) 标记一下GC Roots能够关联的对象,并且修改TAMS的值,需暂停用户线程 
2)并发标记(Concurrent Marking) 从GC Roots进行可达性分析,找出存活的对象,与用户线程并发执行
3)最终标记(Final Marking) 修正在并发标记阶段因为用户程序的并发执行导致变动的数据,需暂停用户线程 
4)筛选回收(Live Data Counting and Evacuation) 对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间制定回收计划

 

7.4.8 垃圾收集器分类

串行收集器:Serial和Serial Old

只能有一个垃圾回收线程执行,用户线程暂停。适用于内存比较小的嵌入式设备

并行收集器[吞吐量优先]: Parallel Scanvenge 和 Parallel Old

多条垃圾收集线程并发工作,但此时用户线程处于等待状态。适用于科学计算、后台处理等交互场景

并发收集器[停顿时间优先] : CMS 和 G1

用户线程和垃圾收集线程同时执行,(但并不一定并行,可能是交替执行),垃圾收集线程在执行的时候不会停顿用户线程的运行。适用于相对时间有要求的场景,比如web

7.4.9 理解吞吐量和停顿时间

  • 吞吐量-> 运行用户代码时间/(用户代码时间+垃圾收集时间)

  • 停顿时间->垃圾收集器进行垃圾回收终端应用执行响应的时间

停顿时间越短就越适合需要和用户交互的程序(比如电商),良好的响应速度能提升用户的体验。

高吞吐量则可以高效地利用CPU时间,尽快地完成程序的运行任务,主要适合后台运算而不太需要交互的任务。(比如定时任务)

小结:这两个指标是评价垃圾回收器好坏的标准,其实调优也是在观察这两个变量。

 

7.4.10 如何选择适合的垃圾收集器

官网地址

  • 优先调整堆的大小,让服务器自己选择

  • 如果内存小于100M,使用SerialGC

  • 如果是单核,并对停顿时间没有要求,使用 SerialGC 或自选

  • 如果允许停顿时间超过1秒,选择ParalleGC或自选

  • 如果响应时间最重要,并且不能超过1秒,使用ConcMarkSweepGC 或G1GC

7.4.11 G1深入了解

JDK7开始使用,JDK8非常成熟,JDK 9 默认使用的垃圾收集器,适合新老生代。

判断是否需要使用G1收集器?

1)50%以上的堆被存活对象占用
2)对象分配和年龄 变化非常大
3)垃圾回收时间比较长

7.4.12 如何开启需要的垃圾收集器

(1)串行 
    -XX:+UseSerialGC 
    -XX:+UseSerialOldGC 
(2)并行(吞吐量优先): 
    -XX:+UseParallelGC 
    -XX:+UseParallelOldGC 
(3)并发收集器(响应时间优先) 
    -XX:+UseConcMarkSweepGC 
    -XX:+UseG1GC

G1调优

选项/默认值说明
-XX:+UseG1GC使用 G1 (Garbage First) 垃圾收集器
-XX:MaxGCPauseMillis=n设置最大GC停顿时间(GC pause time)指标(target). 这是一个软性指标(soft goal), JVM 会尽量去达成这个目标.
-XX:InitiatingHeapOccupancyPercent=n启动并发GC周期时的堆内存占用百分比. G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示“一直执行GC循环”. 默认值为 45.
-XX:NewRatio=n新生代与老生代(new/old generation)的大小比例(Ratio). 默认值为 2.
-XX:SurvivorRatio=neden/survivor 空间大小的比例(Ratio). 默认值为 8.
-XX:MaxTenuringThreshold=n提升年老代的最大临界值(tenuring threshold). 默认值为 15.
-XX:ParallelGCThreads=n设置垃圾收集器在并行阶段使用的线程数,默认值随JVM运行的平台不同而不同.
-XX:ConcGCThreads=n并发垃圾收集器使用的线程数量. 默认值随JVM运行的平台不同而不同.
-XX:G1ReservePercent=n设置堆内存保留为假天花板的总量,以降低提升失败的可能性. 默认值是 10.
-XX:G1HeapRegionSize=n使用G1时Java堆会被分为大小统一的的区(region)。此参数可以指定每个heap区的大小. 默认值将根据 heap size 算出最优解. 最小值为 1Mb, 最大值为 32M

When I let go of what I am , I become what I might be.
走出舒适圈,遇见更好的自己。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值