JVM(四)——垃圾回收机制

本文介绍了垃圾收集的基本概念,包括如何判断对象是否可回收的方法,如引用计数法和根搜索法。并详细解释了几种垃圾回收算法:标记-清除算法、复制算法、标记整理算法以及分代收集算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

垃圾收集(Garbage Collection, GC),需要完成三件事情:

    哪些内存需要回收?

    什么时候回收?

     如何回收?

对象已死?

      堆中存在着所有的对象实例,垃圾回收器在对堆进行回收之前,就要确定这些对象有哪些还“存活”着,哪些已经“死去”(即不可能再被任何途径使用的对象)。


1、引用计数法:

      为每个对象增加一个字段记录被引用的次数,并由运行时跟踪和更新引用的总数;缺陷:如果两个对象互相引用,这两个对象是永远不能通过引用计数法回收的。


2、根搜索法

      在主流的商用程序语言中(Java和C#,甚至包括前面提到的古老的Lisp),都是使用根搜索算法(GC Roots Tracing)判定对象是否存活的。这个算法的基本思路就是通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。如图3-1所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

      在Java语言里,可作为GC Roots的对象包括下面几种:

             虚拟机栈(栈帧中的本地变量表)中的引用的对象。

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

             方法区中的常量引用的对象。

             本地方法栈中JNI(即一般说的Native方法)的引用的对象。

垃圾回收算法

1、标记-清除算法

     标记—清除算法包括两个阶段:“标记”和“清除”。在标记阶段,确定所有要回收的对象,并做标记。清除阶段紧随标记阶段,将标记阶段确定不可用的对象清除。

      标记—清除算法是基础的收集算法,标记和清除阶段的效率不高,而且清除后回产生大量的不连续空间(碎片),这样当程序需要分配大内存对象时,可能无法找到足够的连续空间。

回收前:

 

回收后:

 

白色:表示未被使用

绿色:表示正在使用

蓝色:表示即将回收

2、复制算法

复制算法是把内存分成大小相等的两块,每次使用其中一块,当垃圾回收的时候,把存活的对象复制到另一块上,然后把这块内存整个清理掉。

复制算法实现简单,运行效率高,但是由于每次只能使用其中的一半,造成内存的利用率不高。现在的JVM用复制方法收集新生代,由于新生代中大部分对象(98%)都是朝生夕死的,所以两块内存的比例不是1:1(大概是8:1)。

回收前:

 

回收后:

 

3、标记整理算法

标记—整理算法和标记—清除算法一样,但是标记—整理算法不是把存活对象复制到另一块内存,而是把存活对象往内存的一端移动,然后直接回收边界以外的内存。

标记—整理算法提高了内存的利用率,并且它适合在收集对象存活时间较长的老年代。

回收前:

 

回收后:

 

4、分代收集算法

分代收集是根据对象的存活时间把内存分为新生代和老年代,根据个代对象的存活特点,每个代采用不同的垃圾回收算法。新生代采用标记—复制算法,老年代采用标记—整理算法。

 

垃圾回收器

 

### JVM 垃圾回收机制原理 在 Java 虚拟机 (JVM) 中,垃圾回收的主要目标是在不影响应用程序性能的情况下尽可能高效地清理未使用的对象并释放内存。为了实现这一目标,在进行垃圾回收前,首要任务是确定哪些对象可以被认为是“垃圾”,即那些不再被程序引用的对象[^1]。 #### 判断对象存活的方法 两种主要的技术用于判定对象是否仍然活跃: - **引用计数法**:此方法为每个对象维护一个计数器,记录有多少其他对象持有对该对象的引用。一旦某个对象的引用次数降为零,则认为该对象已死亡,可作为垃圾处理。然而,这种方法难以解决循环引用的问题,因此并未广泛应用于现代 JVM 实现中[^5]。 - **可达性分析算法**:这是当前大多数 JVM 使用的方式。从一组称为“GC Roots”的根节点集合出发,遍历整个对象图谱中的所有路径。如果无法通过任何一条路径到达某对象,则表明这个对象已经不可访问,因而标记为待删除状态。典型的 GC Root 包括正在执行的方法局部变量表内的本地变量、活动线程栈帧里的参数以及 JNI 引用等特殊类型的引用[^3]。 ### 垃圾回收过程概述 一旦确认了哪些对象应该被淘汰之后,接下来的工作便是实际执行回收操作。这通常涉及到两个阶段——标记和清除: - **标记阶段**:扫描堆区,查找所有可以从 GC Roots 访问到的对象,并将其标记为活体; - **清除阶段**:移除未被标记的对象,并整理剩余的空间以便后续新对象分配时能够更有效地利用碎片化区域。 值得注意的是,上述描述简化了很多细节,真实的垃圾收集流程可能会更加复杂,具体取决于所选用的具体垃圾收集器及其配置选项。 ### 不同类型的垃圾回收器 JVM 提供了几种不同的垃圾回收器,每一种都具有独特的特性和适用场景: - **Serial GC**:这是一种单线程工作的简单垃圾回收器,适合于小型应用或客户端环境下的短期运行任务。由于其简单的结构设计,使得它易于理解和调试,但在多核处理器上效率较低[^2]。 除了 Serial GC 外,还有 Parallel GC、CMS(Concurrent Mark-Sweep)、G1(Garbage First),ZGC 和 Shenandoah 等更为先进的并发/低延迟型垃圾回收器可供选择,它们各自优化了不同方面的需求,比如吞吐量最大化或是最小停顿时间等等。 ```java // 示例代码展示如何设置特定的垃圾回收器 public class GCTest { public static void main(String[] args) { System.setProperty("java.gc", "G1"); // 设置使用G1垃圾回收器 // ... 应用逻辑 ... } } ```
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值