一.标记阶段:引用计数算法【Java垃圾回收器中未使用】
1.1 概述
- 垃圾标记阶段:在堆中几乎存放着所以的对象实例,在GC执行垃圾回收之前,首先需要区分哪些对象存活着,哪些已经死亡。只有被标记为死亡的对象,GC在执行垃圾回收时,才会释放掉其所占内存空间。这个过程称之为垃圾标记阶段
- 判断对象存活的方式:引用计数算法【Reference Counting】 和 可达性分析算法
1.2引用计数算法
- 对每个对象保存一个整型的引用计数器属性 ,用于记录对象被引用的情况
- 对于对象A,只要有任何一个对象引用的A,则A的引用计数器加1,当引用失效,则A的引用计数器就减1。当引用计数器为0,则表示A对象可以被回收
- 引用计数算法评价:
- 优点:实现简单,垃圾对象便于标识;判定效率高,回收没有延迟
- 缺点:
①最严重的缺点是无法处理循环引用情况,这是条致命缺陷,导致Java垃圾回收器中没有使用此算法
②需要单独的字段存储计数器,增加了空间开销
③每次赋值都要更新计数器,伴随加减法,增加 时间开销
引用计数算法--循环引用问题.png
- Python支持引用技术算法和垃圾收集机制,它针对引用技术的缺陷,通过
①手动解除
②使用弱引用weakref【只要GC,就会被回收】,weakref是Python提供的标准库,旨在解决循环引用
二.标记阶段:可达性分析算法【根搜索算法或追踪性垃圾收集】
2.1概述
- 可达性分析算法是以根对象集合(GC Roots)为起点,按照从上往下的方式搜索被根对象集合连接的目标对象是否可达
- 使用可达性分析算法后,内存中存活的对象都会被根对象集合直接或间接的连接着,搜索走过的路径称之为引用链【Reference Chain】
- 如果目标对象没有任何引用链连接,则可以被标记为垃圾对象
- 特点:实现简单、执行高效、解决了循环引用问题,防止了内存泄漏
-
GC Roots:是一组必须活跃的引用
可达性分析算法.png
2.2 GC Roots
- Java于洋中,GC Roots包含以下几类元素
①虚拟机栈中引用的对象【如各个线程被调用的方法中使用到的参数、局部变量等】
②本地方法栈内JNI(本地方法)引用的对象
③方法区中类静态属性引用的对象【Java类的引用类型静态变量】
④方法区中常量引用的对象【如 String table里的引用,JDK17起,移动到堆中了】
⑤所有被同步锁持有的对象
⑥其他等 - 除了这些固定的GC Roots集合以外,还可能有“临时对象”加入,如:分代收集和局部回收
- 如果要使用可达性分析算法,分析工作必须在一个能保证一致性的快照中进行,这点也就导致GC进行时必须“STW(Stop the World)”的一个重要原因
网友评论