JVM-垃圾检测和回收相关知识点

707 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

垃圾检测算法

引用计数法

工作原理:

  • 遍历堆中的全部实例,实例每被引用一次计算器+1,不再被引用计数器-1,遍历完找到那些计算器为0的对象的过程。(计数器为0的被视为垃圾)

存在的问题:

  • 如果两个对象循环引用的话,就无法回收
  • 找垃圾的时候每次都有遍历所有实例会损耗性能
可达性分析法

工作原理:

  • 从GC Roots(GC起点)出发,遍历实例,能访问到的就不是垃圾,访问不到的就是垃圾

哪些对象可以作为GC ROOTS

  • 局部变量表:正在执行的函数的参数,临时变量,临时值
  • 方法区中的静态变量:类中的静态变量
  • 方法区中的常量池:常量池中的常量引用实例
  • 本地方法栈中的变量:JNI调用Native方法所引用的实例
  • 同步锁持有的对象

垃圾回收算法

复制算法

image.png

复制算法的优点是保证空间连续,算法实现逻辑相对简单,缺点是浪费空间

标记清除

image.png

标记清除算法的优点是算法效率高,实现相对简单,缺点是不能保证空间的连续性。

标记整理

image.png

标记整理算法的优点是能够保证空间连续性,缺点是效率低于标记清除,算法实现难度相对较大。

HotSpot中的垃圾回收器

串行回收器(Client模式下默认垃圾回收器)

Serial

  • 是jdk1.3之前,年轻代唯一的回收器
  • 采用的垃圾回收算法是复制算法
  • 负责Young GC

Serial Old

  • 采用的垃圾回收算法是标记整理算法
  • 负责Old GC
并行回收器

并行回收器有

  • ParNew ,
  • Parallel Scavenge 采用复制算法 ,作用在年轻代
  • parallel old 采用标记整理算法,作用在老年代

相比串行的提升了GC的吞吐量

Parallel 是Java8默认的回收器

并发回收器
  • G1是java9默认的回收器,不再基于分代回收模型
  • ZGC是在java11引入,不再基于分代回收模型
  • CMS主要用于老年代,也可以用于年轻代
CMS(采用标记清除算法)

image.png

CMS的三次标记

  • 初始标记:会STW,但是只标记到GC Roots直接引用的实例(第一级),所以STW很短暂
  • 并发标记:从初始标记的对象开始,遍历全部关联实例,耗时最久但可以与用户线程并行执行,不会执行STW
  • 重新标记:STW 修正并发标记时,用户线程导致标记不准确的情况,也就是脏实例的问题
G1分区回收

image.png

  • 将内存划分为多个大小相等的区里区域(Region),这些区域包含了逻辑上的年轻代和老年代
  • Humongous用来专门存储大实例
  • 区域之间时复制算法,但整体可以看作是标记整理算法
  • 可以只针对部分区域进行垃圾回收,所以可以与用户线程交替进行,缩短STW
  • 可以设置一定时间内,允许垃圾回收的时间,来实现可预测的STW