Java教程

关于JAVA的各种垃圾回收算法

本文主要是介绍关于JAVA的各种垃圾回收算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

关于JAVA的各种垃圾回收算法

文章目录

      • 关于JAVA的各种垃圾回收算法
      • 1.垃圾标记阶段算法
        • 引用计数算法
        • ⭐ 可达性分析算法
      • 2.垃圾清除阶段
        • ⭐ 标记 - 清除(Mark - Sweep)算法
        • ⭐ 复制(Copying)算法
        • ⭐ 标记 - 压缩 (Mark - Compact)算法
      • 3.其他
        • 分代收集算法
        • 增量收集算法
        • 分区算法

1.垃圾标记阶段算法

​ 判断对象是否存活,找到成为垃圾的对象。

​ 当一个对象已经不被任何存活的对象继续引用的时候,则判断该对象已经死亡。

引用计数算法

概念:

​ 对每一个对象保存一个整形的应用计数器属性。用于记录对象被引用的情况。

​ 当引用计数器的值为0,即表示该对象不可能再被使用,可进行回收。

致命缺点: 无法处理循环引用的情况。

⭐ 可达性分析算法

概念:

可达性分析算法是根据GC Roots为起始点,按照从上到下的方式搜索被根对象集合所连接的目标对象是否可达。

GC Roots包括:

  • ⭐ 虚拟机栈中引用的对象

  • ⭐ 本地方法栈中引用的对象

  • ⭐ 方法区中类静态属性引用的对象

  • 字符串常量池中的引用

  • 被同步锁synchronized持有的对象

  • Java虚拟机内部的引用(基本数据类型对应的Class对象,常驻异常对象,系统类加载器)

2.垃圾清除阶段

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

使用空间列表分配对象空间

执行过程:

​ 当堆中的触发垃圾回收时,会停止整个程序(STW),然后分别进行标记清除两个步骤。

标记 :标记所有可达的对象,及所有被引用的对象。将其存放在对象的Header中。

清除 :遍历所有堆中对象,如果没有标记,则清除。

缺点: 效率低;会导致空间碎片化

⭐ 复制(Copying)算法

Eden,Surviver区用的就是这种算法。

使用指针碰撞分配对象空间

执行过程:

将内存空间划分成两个部分。一处作为正在使用的内存,一处作为空闲的内存。在执行垃圾回收时,将可达对象复制到空闲内存区域。两块内存区域互换。如此往复。

优点: 效率高;不会出现碎片问题

缺点: 需要两倍的内存空间;引用关系会发生变化,指针需要改变。

⭐ 标记 - 压缩 (Mark - Compact)算法

老年代用的就是这种算法。

使用指针碰撞分配对象空间

执行过程:

第一阶段和标记-清除算法一样,从根节点开始标记所有被引用的对象;第二阶段将所有的存活对象压缩到内存的一端,按照顺序排放,之后清理边界外的所有空间。

优点: 不会出现碎片化问题;消除了复制算法中内存减半的代价

缺点: 效率低;引用关系会发生变化,指针需要改变;移动的过程中需要STW

3.其他

分代收集算法

在Java中不同的对象的生命周期是不一样的。因此,不同生命周期的对象采用不同的收集方式,可以提高回收的效率。

年轻代:

特点:区域较小,对象生命周期短,回收频繁

复制算法很好的符合了年轻代对象的特点。

老年代:

特点:区域较大,对象生命周期长,存活率高,回收频率低

Mark阶段的开销与存活对象的数量成正比

Sweep阶段的开销与所管理区域的大小呈正相关

Compact阶段的开销与存活对象的数据成正比

CMS回收器:

CMS回收期是基于Mark-Sweep算法实现的,对于对象回收率很高。而面对碎片问题,CMS采用基于Mark-Compact算法的Serial Old回收期作为补偿措施;当内存回收不佳(碎片导致的Concurrent Mode Failure时),将采用Serial Old执行Full GC以达到对老年代内存的整理。

增量收集算法

增量收集算法的基础仍然是标记-清除算法和复制算法。为了解决在垃圾回收时发生的STW。如果此时的STW时间过长,将会严重影响用户体验或者系统的稳定性。因此可以让垃圾收集线程和应用程序线程交替执行。每次垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。

优点: 避免STW时间过长,减少系统的停顿时间。

缺点: 切换线程和上下文转化会使得垃圾回收成本上升,造成系统吞吐量下降。

分区算法

为了更好地控制GC产生的停顿时间,将一块大的内存区域分割成多个小块,根据目标的停顿时间,每次合理回收若干个小区间,而不是整个堆空间,从而减少一次GC产生的停顿。

分代算法将按照对象的生命周期长短划分为两个部分,分区算法将堆空间划分成连续的不同小区间region。

每一个region都是独立使用的,独立回收。这种算法的好处是可以控制一次回收多少个小区间。每个region可能会存放Eden、Survivor、Old、Humongous的数据。

这篇关于关于JAVA的各种垃圾回收算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!