1797 字
9 分钟
JVM垃圾回收算法

垃圾回收算法#

image.png

【Java虚拟机】JVM垃圾回收机制和常见回收算法原理-腾讯云开发者社区-腾讯云

垃圾回收机制#

(1)什么是垃圾回收机制(Garbage Collection, 简称GC)

  • 指自动管理动态分配的内存空间的机制,自动回收不再使用的内存,以避免内存泄漏和内存溢出的问题
  • 最早是在1960年代提出的,程序员需要手动管理内存的分配和释放
  • 这往往会导致内存泄漏和内存溢出等问题,同时也增加了程序员的工作量,特别是C++/C语言开发的时候
  • Java语言是最早实现垃圾回收机制的语言之一,其他编程语言,如C#、Python和Ruby等,也都提供了垃圾回收机制

(2)JVM自动垃圾回收机制

  • 指Java虚拟机在运行Java程序时,自动回收不再使用的对象所占用的内存空间的过程
  • Java程序中的对象,一旦不再被引用会被标记为垃圾对象,JVM会在适当的时候自动回收这些垃圾对象所占用的内存空间
  • 优点
  • 减少了程序员的工作量,不需要手动管理内存
  • 动态地管理内存,根据应用程序的需要进行分配和回收,提高了内存利用率
  • 避免内存泄漏和野指针等问题,增加程序的稳定性和可靠
  • 缺点
  • 垃圾回收会占用一定的系统资源,可能会影响程序的性能
  • 垃圾回收过程中会停止程序的执行,可能会导致程序出现卡顿等问题
  • 不一定能够完全解决内存泄漏等问题,需要在编写代码时注意内存管理和编码规范

垃圾回收算法#

引用计数法#

跟踪每个对象被引用的次数,当引用次数为0 的时候,可以将该对象回收。

优点是实现简单,缺点是循环引用没办法回收,而且引用计数器消耗大。

image.png

image.png

可达性分析算法#

  • 可达性分析算法的基本思想是通过一系列的“GC Roots”对象作为起点进行搜索。
  • 如果“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。
  • 被判定为不可达的对象要成为回收对象,要至少经历两次标记过程。
  • 如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为“引用链”,当一个对象到 GC Roots 没有任何的引用链相连时(从 GC Roots 到这个对象不可达)时,证明此对象不可用。

image.png

image.png

什么是GC ROOT#

image.png

image.png

垃圾回收算法之标记-复制算法#

  • 标记算法是一种常见的垃圾回收算法,它的基本思路是将Java堆分为两个区域:一个活动区域和一个空闲区域
  • 在垃圾回收过程中,首先标记所有被引用的对象
  • 然后将所有被标记的对象复制到空闲区域中,最后交换两个区域的角色,完成垃圾回收
  • 标记复制算法的详细实现步骤
    • 将Java堆分为两个区域:一个活动区域和一个空闲区域,初始时,所有对象都分配在活动区域中
    • 从GC Roots对象开始,遍历整个对象图,标记所有被引用的对象
    • 对所有被标记存活的对象进行遍历,将它们复制到空闲区域中,并更新所有指向它们的引用,使它们指向新的地址
    • 对所有未被标记的对象进行回收,将它们所占用的内存空间释放
    • 交换活动区域和空闲区域的角色,空闲区域变为新的活动区域,原来的活动区域变为空闲区域
    • 当空闲区域的内存空间不足时,进行一次垃圾回收,重复以上步骤。
  • 优点
    • 如果内存中的垃圾对象较多,需要复制的对象就较少,则效率高
    • 清理后,内存碎片少
  • 缺点
    • 标记复制算法的效率较高,但是预留一半的内存区域用来存放存活的对象,占用额外的内存空间
    • 如果出现存活对象数量比较多的时候,需要复制较多的对象 效率低
    • 假如是在老年代区域,99%的对象都是存活的,则性能底,所以老年代不适合这个算法

image.png

复制过程如下,GC会将五个存活对象复制到to区,并且保证在to区内存空间上的连续性。

image.png

最后,将from区中的垃圾对象清除。

image.png

垃圾回收算法之标记-整理算法#

标记-整理算法(Mark-Compact Algorithm) 是一种常见的垃圾回收(GC)算法,主要用于解决 标记-清除算法(Mark-Sweep) 产生的内存碎片问题。它通常被用于 Java 的老年代(Old Generation)垃圾回收中。

标记-整理算法主要分为两大阶段:

标记阶段(Mark Phase)

和标记-清除算法一样,从 GC Roots 出发,遍历所有可达对象,并将其标记为“存活”状态。

整理阶段(Compact Phase)

将所有存活对象向内存的一端移动(通常是低地址方向)。

移动后会更新对象引用地址,以保证程序继续正确运行。

移动完成后,直接清理边界以后的内存空间。

特点标记-清除算法标记-整理算法
内存碎片会产生碎片不会产生碎片
效率清除快(只清除不可达对象)较慢(需要移动对象)
适用场景适用于对象回收率较高的情况适用于对象存活率较高的情况

垃圾回收算法之-分代算法#

image.png

新生代分为eden区、from区、to区,老年代是一整块内存空间

分代算法将内存区域分为两部分:新生代和老年代。

根据新生代和老年代中对象的不同特点,使用不同的GC算法。

新生代对象的特点是:创建出来没多久就可以被回收(例如虚拟机栈中创建的对象,方法出栈就会销毁)。也就是说,每次回收时,大部分是垃圾对象,所以新生代适用于复制算法。

老年代的特点是:经过多次GC,依然存活。也就是说,每次GC时,大部分是存活对象,所以老年代适用于标记压缩算法。

image.png

image.png

分代算法执行过程#