深入理解JVM02.0 垃圾回收GC算法

101 阅读3分钟

本文章的内容来自以下的内容
【JVM调优实战】对比:golang与java的GC(全网首讲)_哔哩哔哩_bilibili
《深入理解Java虚拟机- -jvm高级特性与最佳实践》

常用的垃圾查找算法

记数法

有一个引用,+1,如果引用变为0,那就判定为垃圾。python使用这个算法

根可达

那什么是根呢? Object 这个对象就是根!

Object C = new Object();
## 根不可达是什么?
C = null

常用的垃圾回器收算法(GC算法)

标记-清除(Mark-Sweep)算法

标记完成之后,直接释放内存,后面的程序就可以直接使用这块内存了!python使用这个算法
缺点:内存碎片太多,不方便使用

copying 复制算法

只使用一半内存,在清理垃圾的时候,复制数据到另一半内存并排列好。
缺点:只能用一半,浪费内存

标记-压缩(标记-整理)Mark-Compact算法

在回收垃圾的时候,顺便就排列好。
缺点:效率低,

三种算法各有各的毛病,三种的综合运用,诞生了各种各样的算法!

image.png

堆内存的逻辑分区

image.png

新生代和老年代

新生代:整体使用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 等 image.png

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"事件

image.png

四个阶段

  • 初始标记
    • STW阶段,时间特别短
    • 找root
  • 并发标记
    • 三色标记算法(Golong也使用该算法)
  • 重新标记
    • STW阶段,时间特别短
    • 清理标记错误的垃圾
    • 1,原来不是垃圾,变成了垃圾
    • 2,原来是垃圾,被重新启用
  • 并发清理
    • 垃圾收集器并发地清除所有未被标记的对象

具体了解CMS算法和常见面试问题,请阅读下面的链接: