JVM垃圾收集器

垃圾收集算法:为实现垃圾回收提供理论支持
垃圾收集器:利用垃圾收集算法,实现垃圾回收的实践落地
垃圾收集器组合

术语

术语-Stop The World
简写为STW ,也叫全局停顿,Java代码停止运行,native代码继续运行,但不能与JVM进行交互
原因:多半由于垃圾回收导致;也可能由Dump线程、死锁检查、Dump堆等导致
危害:服务停止、没有响应;主从切换、危害生产环境

术语-并行收集Vs并发收集
并行收集:指多个垃圾收集线程并行工作,但是收集的过程中用户线程(你的业务线程)还是处于等待状态的
并发收集:指用户线程与垃圾收集线程同时工作

术语-吞吐量
CPU用于运行用户代码的时间与CPU总消耗时间的比值
公式:运行用户代码时间/ (运行用户代码时间+垃圾收集时间)

新生代收集器

新生代收集器-Serial

Serial 收集器执行过程
Serial 收集器执行过程

Serial 收集器特点:
简单、高效、单线程
收集过程全程 stop the world

Serial 收集器适用场景
客户端程序,应用以-client模式运行时,默认使用的就是Serial
单核机器

新生代收集器-ParNew

Serial收集器的多线程版,除使用了多线程以外,其他和Serial收集器一样,包括:JVM参数、Stop The World的表现、垃圾收集算法都是一样的。

ParNew 收集器-执行过程

ParNew收集器适用场景
主要用来和CMS收集器配合使用

新生代收集器-Parallel Scavenge收集器

也叫吞吐量优先收集器
采用的也是复制算法
也是并行的多线程收集器,这一点和ParNew类似

Parallel Scavenge收集器-特点

  • 可以达到一个可控制的吞吐量
    -XX:MaxGCPauseMillis :控制最大的垃圾收集停顿时间(尽力)
    -XX:GCTimeRatioi:设置吞吐量的大小,取值0-100,系统花费不超过1/(1 +n)的时间用于垃圾收集

  • 自适应GC策略:可用-XX:+ UseAdptiveSizePolicy打开
    打开自适应策略后,无需手动设置新生代的大小( -Xmn )、Eden与Survivor区的比例( -XX:SurvivorRatio )等参数虚拟机会自动根据系统的运行状况收集性能监控信息,动态地调整这些参数,从而达到最优的停顿时间以及最高的吞吐量

Parallel Scavenge收集器-适用场景
注重吞吐量的场景

老年代垃圾收集器

老年代收集器-Serial Old收集器

Serial收集器的老年代版
采用的是标记-整理算法

Serial Old收集器执行过程

Serial Old收集器执行过程
Serial Old收集器适用场景
可以和Serial/ParNew/Parallel Scavenge这三个新生代的垃圾收集器配合使用
CMS收集器出现故障的时候,会用Servial Old作为后备

老年代收集器 - Parallel Old收集器

Parallel Scavenge收集器的老年代版本
采用标记-整理算法

Parallel Old收集器执行过程
Parallel Old收集器执行过程
Parallel Old收集器-特点
只能和Parallel Scavenge配合使用

Parallel Old收集器适用场景
关注吞吐量的场景

老年代收集器-CMS收集器

CMS 全称: Concurrent Mark Sweep
并发收集器
采用标记-清除算法

在这里插入图片描述

  • 初始标记( initial mark )
    标记GC Roots能直接关联到的对象
    Stop The World(由于这个阶段只标记 GC Roots 能直接关联的对象,标记的对象毕竟少,所以 STW 的时间会很短)

  • 并发标记( concurrent mark )
    找出所有GC Roots能关联到的对象
    由于是并发执行,所以无Stop The World

  • 并发预清理( concurrent-preclean )
    这个阶段不一定会执行,重新标记那些在并发标记阶段,引用被更新的对象(比如说晋升到老年代的对象),从而减少后面重新标记阶段的工作量
    并发执行,无Stop The World

  • 并发可中止的预清理阶段( concurrent-abortable-preclean )
    这个阶段也不一定会执行,和并发预清理做的事情一样,并发执行,无Stop The World
    当Eden的使用量大于 CMSScheduleRemarkEdenSizeThreshold 的阈值(默认2M)时,才会执行该阶段。
    主要作用:允许我们能够控制预清理阶段的结束时机。比如扫描多长时间( CMSMaxAbortablePrecleanTime ,默认5秒)或者Eden区使用占比达到一定阈值( CMSScheduleRemarkEdenPenetration ,默认50% )就结束本阶段

  • 重新标记( remark )
    修正并发标记期间,因为用户程序继续运行,导致标记发生变动的那些对象的标记(比如把已经死亡的对象标记为存活,导致部分垃圾不能回收;把存活的对象标记为死亡,这种情况问题就大了,程序都不能运行了)
    一般来说,重新标记花费的时间会比初始标记阶段长一些 ,但比并发标记的时间短
    存在stop the word

  • 并发清除( concurrent sweep )
    基于标记结果,清除掉要清除前面标记出来的垃圾
    并发执行,无Stop The World
    为什么不是并发整理呢?
    并发清除阶段是并发执行的,如果整理的话需要移动对象位置,很难在并发状态下,一边对线程执行业务,一边进行垃圾回收,回收的同时还移动对象,移动对象的同时还要保证程序不出问题,实现起来太难了。所以是并发清除而不是并发整理

  • 并发重置(concurrent reset)
    清理本次CMS GC的上下文信息,为下一次GC做准备

CMS收集器-优点
Stop The World的时间比较短,只有在初始标记和重新标记的时候会 STW,其他阶段都是并发执行的
大多过程并发执行

CMS收集器-缺点
CPU资源比较敏感
并发阶段可能导致应用吞吐量的降低
无法处理浮动垃圾
不能等到老年代几乎满了才开始收集

  • 预留的内存不够-> Concurrent Mode Failure -> Serial Old 作为后备
  • 可使用CMSInitiatingOccupancyFraction设置老年代占比达到多少就触发垃圾收集,默认68%

内存碎片

  • 标记清除所产生的碎片
  • UseCMSCompactAtFullCollection :在完成Full GC后是否要进行内存碎片整理,默认开启
  • CMSFullGCsBeforeCompaction :进行几次Full GC后就进行一 次内存碎片整理,默认0

CMS收集器-适用场景
希望系统停顿时间短,响应速度快的场景,比如各种服务器
应用程序

CMS收集器-总结
1.初始标记
2.并发标记
3.并发预清理(可能发生)
4.并发可中止的预清理阶段(可能发生)
5.重新标记
6.并发清除
7.并发重置

G1 收集器

既可以在老年代又可以在新生代
G1 收集器-内存布局
G1 会把 Humongous 当做老年代的一部分,其中 Humongous 存放大对象,如果一个对象特别大,一个 Humongous 放不下,则会放在连续个 Humongous 中

G1收集器-设计思想
内存分块( Region )
跟踪每个Region里面的垃圾堆积的价值大小
勾建一个优先列表,根据允许的收集时间,优先回收价值高的Region
G1 的全称:garbage first

G1收集器-垃圾收集机制

  • Young GC
    所有Eden Region都满了的时候,就会触发Young GC
    伊甸园里面的对象会转移到Survivor Region里面去
    原先Survivor Region中的对象转移到新的Survivor Region中,或者晋升到Old Region
    空闲Region会被放入空闲列表中,等待下次被使用
  • Mixed GC
    老年代大小占整个堆的百分比达到一定阈值(可用-XX:InitiatingHeapOccupancyPercent指定,默认45% ) , 就触发
    Mixed GC会回收所有Young Region ,同时回收部分Old Region
    G1 收集器-Mixed GC 执行过程
  1. 初始标记( Initial Marking )
    标记GC Roots能直接关联到的对象,和CMS类似
  2. 并发标记 ( Concurrent Marking )
    同CMS的并发标记
    并发执行,没有 STW
  3. 最终标记 ( Final Marking )
    修正在并发标记期间引起的变动
    存在Stop The World
  4. 筛选回收( Live Data Counting and Evacuation )
    对各个Region的回收价值和成本进行排序
    根据用户所期望的停顿时间( MaxGCPauseMillis )来制定回收计划,并选择一些Region回收
    • 回收过程:
      选择一系列Region 构成一个回收集
      把决定回收的Region中的存活对象复制到空的Region中
      删除掉需回收的Region ->无内存碎片
      存在 STW
  • Full GC
    复制对象内存不够,或者无法分配足够内存(比如巨型对象没有足够的连续分区分配)时,会触发Full GC
    Full GC模式下,使用Serial Old模式
    G1优化原则:尽量减少Full GC的发生

G1收集器-减少Full GC的思路?
增加预留内存(增大-XX:G1ReservePercent ,默认为堆的10% )
更早地回收垃圾(减少-XX:InitiatingHeapOccupancyPercent ,老年代达到该值就触发Mixed GC ,默认45% )
增加并发阶段使用的线程数(增大XX:ConcGCThreads )

G1收集器-特点.
可以作用在整个堆.
可控的停顿时间:MaxGCPauseMillis= 200
无内存碎片

G1收集器-适用场景
占用内存较大的应用(6G以上)
替换CMS垃圾收集器

G1收集器-总结
内存分Region
包括Young GC、Mixed GC、 Full GC
Mixed GC步骤和CMS有类似之处,但也有很多差异

G1 or CMS?
对于JDK8,都可以用
如果内存<=6G,建议用CMS;如果内存>6G,考虑使用G1(经验之谈)

如果> JDK 8 :用G1,CMS从JDK 9已经被废弃了

其他垃圾收集器
Shenandoah
ZGC
Epsilon

如何选择垃圾收集器?
关注的主要矛盾点是什么?
基础设施
JDK

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值