本文主要对JVM的垃圾回收算法和垃圾收集器的实现机制和使用场景进行了总结。

Java GC

对象生命周期

  • 引用计数法
    无法解决循环引用的问题

  • 可达性分析算法
    从GC Roots看对象是否可达:

    1
    2
    3
    4
    虚拟机栈(栈中的本地变量表)中引用的对象
    本地方法栈中JNI(即Native方法)引用的对象
    方法区中类静态属性的变量
    方法区中常量引用的变量

引用

  • 强引用
    只要强引用存在就不会回收

  • 软引用
    只有内存不够才会回收
    浏览器的后退按钮

  • 弱引用
    不管内存够不够都会回收

  • 虚引用
    作为回收对象时的通知
    回收方法区

  • 废弃常量

  • 无用的类
    大量反射、动态代理、CGLib频繁自定义的ClassLoader
    需要有类的卸载功能
    通过更换ClassLoader实现类的卸载

垃圾回收算法

标记-清除算法
效率和内存碎片的问题

复制算法
分区复制回收
适用于对象存活率较低的场景(新生代)

标记-整理算法
标记-清除-整理
使用与对象存活率较高的场景(老生代)

分代收集算法
根据对象存活周期分为几块

  • 新生代
    复制算法

  • 老生代
    标记-清除算法
    标记-整理算法

垃圾收集器

Serial收集器

  • 缺点
    单线程处理,需要暂停其他所有线程

  • 优点
    简单

ParNew收集器
Serial收集器的多线程实现

Parallel Scavenge收集器
以吞吐量为目标
吞吐量=用户代码运行时间/(用户代码运行时间 + GC时间)

Serial Old收集器
Serial收集器的老年代版本

Parallel Old收集器
Parallel Scavenge收集器的老年代版本

CMS收集器
以获取最短停顿时间为目标
分为初始标记、并发标记、重新标记、并发清除四个阶段

  • 优点
    停顿时间短

  • 缺点
    消耗较多的CPU资源
    会产生较多的内存碎片

  • 为什么需要STP?
    处理起来简单,不用管并发的问题

G1收集器

  • 特点
    更少的GC停顿时间
    可预测的GC停顿时间
    不牺牲过多的吞吐量
    不需要过多的堆内存
Contents
  1. 1. 对象生命周期
  2. 2. 垃圾回收算法
  3. 3. 垃圾收集器