判断对象可回收
- 引用计数法
-
可达性分析算法
以 GC Roots 作为起点,没有与 GC Roots 引用链相连的对象,且没有必要再执行 finalize() 方法时,判断为可回收对象。
GC Roots
虚拟机栈中引用的对象
- 方法区中静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即Native方法)引用的对象
- Java 虚拟机内部的引用(基本数据类型对应的Class对象、常驻的异常对象 NullPointException等、系统类加载器);
- 所有被同步锁(synchronized)持有的对象;
方法区的回收
虽然大部分垃圾回收都发生在堆内存中,而且方法区垃圾收集的性价比通常也是较低的。但针对方法区,还是有两部分主要回收的内容:废弃常量和不再使用的类型。
常量是否废弃判断:
- 没有任何字符串对象引用常量池中的该常量;
- 虚拟机中也没有其他地方引用这个字面量;
类型是否不再使用判断:
- 该类的实例都已经被回收;
- 加载该类的类加载器已经被回收;
该类对应的 Class 对象没有任何地方引用(没有地方通过反射访问该类);
垃圾收集算法
标记-清除法
- 标记-复制
-
分代收集分类
部分收集(Partial GC)
- 新生代收集(Minor GC/ Young GC):只收集新生代
- 老年代收集(Major GC/ Old GC):只收集老年代(CMS)
- 混合收集(Mixed GC):整个新生代和部分老年代(G1)
-
分代回收
根据分代垃圾回收,堆内存被分为新生代、老年代区域,新生代与老年代的空间大小比为 1:2。新生代又分为 Eden 、 From Survivor 和 To Survivor,Eden、From 和 To 的空间大小比为 8:1:1。
对象的流转
对象优先分配在 Eden;
- Eden 区空间不足时,触发 Minor GC,Eden 和 From 依然存活的对象直接复制到 To Survivor,分代年龄增加 1;
- 交换 From 与 To;
- 新生代对象移动到老年代分为两种情况:
- 分代年龄达到 15;
- 幸存区相同年龄的对象超过一半,大于等于该年龄的对象移动到老年代;
-
垃圾收集器
Serial
单线程、垃圾收集时暂停用户线程
新生代:标记-复制
-
ParNew
多线程并行收集、垃圾收集时暂停用户线程、新生代收集器
-
Parallel Scavenge
多线程并行收集、吞吐量优先、新生代收集器
-
Parallel Old
多线程并行收集、老年代收集器
-
CMS
响应时间优先、最短回收停顿时间
老年代:标记-清除
收集步骤:
收集步骤
- 初始标记(STW)
- 并发标记
- 最终标记(STW)
- 筛选回收(STW)