本文章的内容来自以下的内容
【JVM调优实战】对比:golang与java的GC(全网首讲)_哔哩哔哩_bilibili
《深入理解Java虚拟机- -jvm高级特性与最佳实践》
常用的垃圾查找算法
记数法
有一个引用,+1,如果引用变为0,那就判定为垃圾。python使用这个算法
根可达
那什么是根呢? Object 这个对象就是根!
Object C = new Object();
## 根不可达是什么?
C = null;
常用的垃圾回器收算法(GC算法)
标记-清除(Mark-Sweep)算法
标记完成之后,直接释放内存,后面的程序就可以直接使用这块内存了!python使用这个算法
缺点:内存碎片太多,不方便使用
copying 复制算法
只使用一半内存,在清理垃圾的时候,复制数据到另一半内存并排列好。
缺点:只能用一半,浪费内存
标记-压缩(标记-整理)Mark-Compact算法
在回收垃圾的时候,顺便就排列好。
缺点:效率低,
三种算法各有各的毛病,三种的综合运用,诞生了各种各样的算法!
堆内存的逻辑分区
新生代和老年代
新生代:整体使用copying算法
新生代的区域分为:
- eden 伊甸区
- suvivor1
- suvivor2
扫描过程:
第一次扫描:先扫描eden区,如果有剩余的,丢到suvivor1里面。整体回收eden区。
第二次扫描,扫描eden和suvivor1,如果有存活的,丢到suvivor2里面,eden和suvivor1整体回收。
第三次扫描:扫描eden和suvivor2,如果有存活的,丢到suvivor1里面,eden和suvivor2整体回收。
根据统计,仅一次扫描,就可以回收大约90%的新生代垃圾。
什么时候FGC(Full GC)
老年代满了就会产生FGC。
GC算法的发展历程
GC算法随着内存的不断扩大而变化
- 几MB到几十MB:Serial
- 几十MB到1G:Parallel
- 1G到几十G:CMS, G1, ZGC 等
Serial 和 Serial Old 单线程
Serial:处理青年区的垃圾,使用Copying算法。
Serial Old:处理老年区的垃圾,使用标记-整理(Mark-Compact)算法
Parallel 和 Parallel Old 多线程
Parallel:处理青年区的垃圾,使用Copying算法。
Parallel Old:处理老年区的垃圾,使用Mark-Sweep算法。
CMS 和 Parallel Scavenge算法
Concurrent Mark Sweep,Concurrent指的是业务线程和垃圾回收线程并发。
CMS算法的主要目标是减少垃圾收集过程中应用程序的停顿时间(也称为"Stop-the-World"事件
四个阶段
- 初始标记
- STW阶段,时间特别短
- 找root
- 并发标记
- 三色标记算法(Golong也使用该算法)
- 重新标记
- STW阶段,时间特别短
- 清理标记错误的垃圾
- 1,原来不是垃圾,变成了垃圾
- 2,原来是垃圾,被重新启用
- 并发清理
- 垃圾收集器并发地清除所有未被标记的对象
具体了解CMS算法和常见面试问题,请阅读下面的链接: