如果某个地方引用了这个对象就+1,如果失效了就-1,当为 0 就会回收。
(二)可达性分析(hotspot)【JVM不可用】无法判定循环引用,造成内存泄漏
在垃圾回收之前,沿着GC Root对象为起点的引用链,扫描对于堆中的对象,找不到则能被回收。
GC Root 根对象(不能被回收)
五种引用 三色标记法GC Root对象有哪些 ?
- Java虚拟机栈(栈帧的本地变量表)中引用的对象。
- 本地方法栈中JNI引用对象。
- 方法区中常量、类静态属性引用的对象。
原版
不可达对象 + 两次标记后仍可回收 == 可回收对象
(1)多标-- 浮动垃圾三色标记法与读写屏障
白色:尚未访问过。
黑色:本对象已访问过,而且本对象 【引用的其他对象】 也全部访问过了。
灰色:本对象已访问过,但是本对象 【引用的其他对象】 尚未全部访问完。 若全部访问后,会转换为黑色。
多标了E,导致E成为浮动垃圾(等下一轮GC,才被清除)
var G = objE.fieldG; // 白色E 引用 白色G objE.fieldG = null; // 灰色E 断开引用 白色G objD.fieldG = G; // 黑色D 引用 白色G
二、垃圾回收算法 (一)标记清除尽管因为D重新引用了G,但因为D已经是黑色了,不会再重新做遍历处理。
结果:G会一直停留在白色集合中,最后被当作垃圾进行清除。 影响程序正确性,不可接受的。
先标记需清除的对象,之后统一回收。
(二)标记整理但是这种方法效率不高,会产生大量不连续的空间碎片,这些碎片很难被重复利用。
先标记存活对象,然后让所有存活对象向一端移动,之后清理端边界以外的内存,解决内存碎片问题。
缺点:要移动对象,需要频繁改动对象的引用地址,速度慢。
将可用内存按容量划分为大小相等的两块,每次只使用其中一块。
当使用的这块空间用完了,就将存活对象复制到另一块,再把已使用过的内存空间一次清理掉。
优点:不会有内存碎片
缺点: 需要占用双倍内存空间
以上三种算法的具体实现
新生代:标记复制 老年代:标记清除 / 标记整理垃圾回收流程:
(1)对象首先分配在伊甸园区域
(2)新生代空间不足时,触发 minorGC,伊甸园和 from 存活的对象使用 copy 复制到 to 中,存活的对象年龄加 1并且交换 from to 。
minor GC 会引发STW,暂停其它用户的线程。等垃圾回收结束,用户线程才恢复运行 。
当对象寿命超过阈值时,会晋升至老年代,最大寿命是15(4bit),寿命保存在对象头中 。
(3)当老年代空间不足,会先尝试触发 minor GC,如果之后空间仍不足,那么触发 full GC,STW的时间更长
| 回收阶段 | 触发条件 | 内容 |
|---|---|---|
| Yong GC | ||
| Yong Coleection + 并发标记 | 当老年代超过一定阈值 | |
| Mixed Collection | 对新生代混合区和老年代进行规模较大的收集 |
年轻代
| 回收器 | 算法 | 应用线程 | 特点 |
|---|---|---|---|
| Serial | 标记复制 | STW | 单线程 串行 |
| ParNew(可与CMS搭配) | 标记复制 (Serial收集器的多线程版本) | STW | 并行多线程 |
| Parallel Scavenge(可与Parallel Old搭配) | 标记复制 | STW | 并行多线程 |
老年代
| 回收器 | 适用场景 | 算法 | 应用线程 | 特点 |
|---|---|---|---|---|
| Serial Old | mark-sweep-compact(标志-清扫-压缩) | STW | 单线程 串行 | |
| Parallel Old | mark-sweep(标志-清扫) | STW | 多线程并行 | |
| Parallel Old |
并发垃圾回收器
| 回收器 | 适用场景 | 算法 | 应用线程 | 特点 |
|---|---|---|---|---|
| CMS(Concurrent MarkSweep ) | 并行,低暂停 | 某阶段会stw | 并发 | |
| G1 | ,低暂停 | 某阶段会stw | 并发 |
GC期间STW,不允许用户线程继续工作
有划时代意义!
第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。
不幸的是,CMS作为老年代的收集器,新生代只能选择ParNew或者Serial收集器中的一个。
初始标记 -> 并发标记 -> 重新标记 -> 并发清理
初始标记:只是标记出GCRoots能直接关联到的对象(所有工作线程会STW短暂暂停)
并发标记:从Gc Roots的直接关联对象开始遍历整个对象图
重新标记:修正并发标记期间,【因用户程序继续运作而导致标记产生变动】
并发清除:清理【标记已经死亡的对象】,释放内存
- 基本不暂停用户线程(仍有STW,但时间很短)
- 当ConcurrentMarkSweep 收集失败时,临时启用Serial Old(该算法会完全阻止应用程序的运行)
新生代:Parallel Scavenge (PS MarkCopy) 老年代:Parallel Old (PS MarkSweep)五、参考博客
相关 VM 参数CMS垃圾回收器详解
| 含义 | 参数 |
|---|---|
| 堆初始大小 | -Xms |
| 堆最大大小 | -Xmx 或 -XX:MaxHeapSize=size |
| 新生代大小 | -Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size ) |
| 幸存区比例(动态) | -XX:InitialSurvivorRatio=ratio 和 -XX:+UseAdaptiveSizePolicy |
| 幸存区比例 (默认8,新生代:伊甸园8, FROM 1,TO 1) | -XX:SurvivorRatio=ratio |
| 晋升阈值 | -XX:MaxTenuringThreshold=threshold |
| 晋升详情(打印) | -XX:+PrintTenuringDistribution |
| GC详情(打印) | -XX:+PrintGCDetails -verbose:gc |
| FullGC 前先MinorGC(默认打开) | -XX:+ScavengeBeforeFullGC |



