垃圾回收
可达性分析算法
在 Java 技术体系中,固定可以作为 GC Roots 的对象包含以下几种
- 在虚拟机栈(栈帧中的本地变量表)中引用的对象,比如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量
- 在方法区中类静态属性引用的对象、比如字符串常量池里面的引用
- 在本地方法栈中JNI引用的对象
- Java 虚拟机内部的引用,比如基本数据类型对应的 Class 对象,一些常驻的异常对象等,还有系统类加载器
- 所有被同步锁持有的对象
垃圾收集器的问题
Serial 垃圾回收期的执行图
ParNew 收集器
Parallel Scavenge 收集器
- Parallel Scavenge 也是一个新生代支持多线程的垃圾回收期,那么和 ParNew 有什么区别呢? 主要是设计目标不同,其他垃圾收集器主要关注点是缩短垃圾收集器垃圾收集时用户停顿的时间,而 Parallel Scavenge 收集器的目标则是打到一个可控制的吞吐量。
- 吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 运行垃圾收集器时间)
- 是不是垃圾收集时间断吞吐量就一定大? 这个就不一定了,如果是单词垃圾收集,可以这么说,但是垃圾收集是很频繁的,如果单次垃圾收集的时间都很短,但是次数却很多,那么吞吐量就不一定高了。
Parallel Scavenge 提供了两个参数用于精确控制吞吐量
CMS 垃圾收集器的目标是获取最短回收停顿时间
- 垃圾收集步骤
- 初始标记(STW)
- 标记一下 GC Roots 可以直接关联的对象,耗时短
- 并发标记
- 从 GC Roots 的直接关联对象开始遍历整个对象图的过程,耗时长但是不需要停止用户线程
- 重新标记(STW)
- 修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录
- 并发清除
- 初始标记(STW)