GC回收机制及算法

本文详细介绍了Java垃圾收集(GC)的各种回收机制和算法,包括引用计数算法、可达性分析算法、标记-清除算法、复制算法、标记-整理算法以及分代收集算法。其中,主流的商用虚拟机采用可达性分析来判断对象是否存活,并重点讨论了新生代和老年代的GC策略。例如,新生代通常使用复制算法,老年代则可能使用标记-整理算法。文章还探讨了不同的垃圾收集器,如Serial、ParNew、Parallel Scavenge、Parallel Old、CMS和G1,以及它们各自的特点和适用场景。
摘要由CSDN通过智能技术生成

GC回收机制及算法

说起垃圾收集(Garbage Collection, GC),大部分人都把这项技术当做Java语言的伴生产物。事实上,GC的历史比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言。当Lisp还在胚胎时期时,人们就在思考GC需要完成的3件事情:
1)哪些内存数据需要回收?
2)什么时候回收?
3)如何回收?

经过半个多世纪的发展,目前内存的动态分配与内存回收技术已经相当成熟,一切看起来都进入了“自动化”时代,那为什么我们还要去了解GC和内存分配呢?答案很简单:当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。

回到我们熟悉的Java语言。Java内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭,因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。而Java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,所以垃圾收集器所关注的是java的堆内存。

哪些内存数据需要被回收?
在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”(即不可能再被任何途径使用的对象)。

引用计数算法

很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。

客观地说,引用计数算法(Reference Counting)的实现简单,判定效率也很高,在大部分情况下它都是一个不错的算法,也有一些比较著名的应用案例,例如微软公司的COM(Component Object Model)技术、使用ActionScript 3的FlashPlayer、Python语言和在游戏脚本领域被广泛应用的Squirrel中都使用了引用计数算法进行内存管理。但是,至少主流的Java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。

可达性分析算法

在主流的商用程序语言(Java、C#,甚至包括前面提到的古老的Lisp)的主流实现中,都是称通过可达性分析(Reachability Analysis)来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

如下图所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。
在这里插入图片描述
在Java语言中,可作为GC Roots的对象包括下面几种:
1)虚拟机栈(栈帧中的本地变量表)中引用的对象。
2)方法区中类静态属性引用的对象。
3)方法区中常量引用的对象。

标记-清除算法

最基础的收集算法是“标记-清除”(Mark-Sweep)算法,如同它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其不足进行改进而得到的。它的主要不足有两个:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

标记—清除算法的执行过程如下图所示。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM(Java虚拟机)的垃圾回收GC机制是自动管理内存的一种机制。它通过自动识别和回收不再使用的对象来释放内存空间,以避免内存泄漏和程序中的内存溢出错误。 JVM中的垃圾回收器负责执行垃圾回收。当对象不再被引用时,垃圾回收器将标记这些对象为垃圾,并将它们从内存中回收。以下是JVM GC回收机制的一般过程: 1. 标记阶段(Marking Phase):从根对象(如线程栈中的引用、静态变量等)开始,垃圾回收器将遍历对象图并标记可达的对象。 2. 清除阶段(Sweeping Phase):垃圾回收器将清除标记为垃圾的对象,并回收它们占用的内存空间。 3. 压缩阶段(Compacting Phase):如果需要,垃圾回收器会对存活的对象进行整理,使它们在内存中连续排列,从而减少碎片化并提高内存的利用率。 4. 再分配阶段(Allocation Phase):如果需要,垃圾回收器会为新对象分配内存空间。 具体的垃圾回收算法和策略可能因不同的JVM实现而异。常见的垃圾回收算法包括标记-清除(Mark and Sweep)、复制(Copying)、标记-整理(Mark and Compact)等。JVM还提供了不同的垃圾回收器,如Serial、Parallel、CMS(Concurrent Mark Sweep)、G1(Garbage-First)等,以满足不同场景下的需求。 总而言之,JVM的垃圾回收机制通过自动识别和回收不再使用的对象来管理内存,确保程序运行时的内存使用效率和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值