Java jvm 标记-清除算法(Mark-Sweep)

标记-清除算法(Mark-Sweep) 是一种经典的垃圾回收算法,它通过两阶段的过程来回收不再使用的对象,具体步骤为:

  1. 标记阶段(Mark Phase):遍历所有对象,标记出所有存活的对象。
  2. 清除阶段(Sweep Phase):回收那些未被标记的对象,即那些不再被任何引用引用的对象。

1. 标记-清除算法的工作原理

标记-清除算法分为两个阶段,分别是 标记阶段清除阶段

1.1 标记阶段
  • 在标记阶段,垃圾回收器会从根对象(例如静态变量、栈上的局部变量等)开始,沿着引用链追踪所有存活的对象。
  • 所有被追踪到的对象都会被标记为“存活”(即:这部分对象是仍然被引用的)。
1.2 清除阶段
  • 一旦标记阶段完成,垃圾回收器就会遍历整个堆空间,清除那些未被标记的对象,这些对象就是不再有任何引用的垃圾对象。
  • 被清除的对象会被从内存中释放,所占的内存空间变为可用。

2. 标记-清除算法的优缺点

2.1 优点
  • 实现简单:标记-清除算法的实现逻辑相对简单,容易理解,基本上是通过两次扫描来完成。
  • 无需移动对象:该算法不涉及对象的移动,因此不会产生像 标记-压缩(Mark-Compact)算法那样的“移动”开销。
2.2 缺点
  • 产生内存碎片:由于清除阶段只是简单地删除垃圾对象,堆空间中可能会留下很多空闲的、分散的内存区域。这些空闲区域无法被有效利用,导致内存碎片的出现。长期运行下去,可能导致堆内存无法得到有效使用。
  • 效率低:垃圾回收过程中需要遍历堆的所有对象,即使某些对象仍然活跃且不需要回收。这会导致回收过程效率较低。
  • 全堆扫描:标记-清除算法需要对堆中的所有对象进行扫描,这对大堆内存应用可能造成较大的性能负担。

3. 标记-清除算法的伪代码

以下是标记-清除算法的伪代码,展示了标记和清除两个阶段的过程:

// 标记阶段
for (each root in roots) {
    mark(root);
}

function mark(object) {
    if (object is not marked) {
        mark(object);
        for (each reference in object.references) {
            mark(reference);
        }
    }
}

// 清除阶段
for (each object in heap) {
    if (object is not marked) {
        free(object);
    }
}

在标记阶段,垃圾回收器从根对象开始,递归地标记所有能够到达的对象。然后,在清除阶段,垃圾回收器遍历堆内存,将那些未被标记的对象删除。

4. 标记-清除算法的改进

标记-清除算法虽然简单有效,但它的缺点也十分明显,尤其是 内存碎片 的问题。因此,很多现代 JVM 都不完全依赖标记-清除算法,而是进行了改进或结合其他算法,以提高性能和减少碎片。

4.1 标记-压缩(Mark-Compact)
  • 标记-压缩算法(Mark-Compact)是在标记-清除算法的基础上进行了改进。在标记阶段标记出存活对象之后,它不会直接清除未标记的对象,而是将所有存活的对象压缩到堆的一个区域内,这样就消除了内存碎片的问题。

  • 优点:消除了内存碎片,提高了堆空间的利用率。

  • 缺点:对象的移动增加了额外的性能开销,尤其是在需要移动大量对象时,可能会导致较高的 CPU 开销。

4.2 复制算法(Copying)
  • 复制算法通过将堆分为两部分,一个用于存放活动对象,另一个用于存放可回收的对象。每次垃圾回收时,它只回收活动区域的对象,并将活动对象复制到另一块内存区域,从而避免了内存碎片。

  • 优点:内存碎片问题得到了较好的解决,且复制的过程比较简单。

  • 缺点:需要额外的内存空间来存放副本,堆的大小需要是双倍的。


5. JVM 中的标记-清除算法

在实际的 JVM 实现中,标记-清除算法并不常单独使用,而是通常作为其他垃圾回收策略的基础,结合其他技术一起工作。比如,JVM 中的 Serial GCParallel GC 都采用了标记-清除算法的思想,但在性能上做了一些改进,以减少内存碎片和提高效率。

  • Serial GC:采用标记-清除算法来进行垃圾回收,但它的效率相对较低。
  • Parallel GC:通过并行化垃圾回收过程,来减少垃圾回收的时间,但也使用标记-清除算法的思想。
  • CMS GC:采用并发标记-清除算法,旨在减少垃圾回收的停顿时间。

6. 总结

标记-清除算法(Mark-Sweep) 是一种简单有效的垃圾回收算法,通过两阶段的标记和清除来释放无用对象占用的内存。它的优点是实现简单,但由于产生内存碎片和效率较低,现代 JVM 更多使用更复杂的垃圾回收算法(如标记-压缩、复制算法等)来解决这些问题。

尽管如此,标记-清除算法仍然是很多垃圾回收器和回收策略中的重要基础,尤其是在对内存管理要求不高或内存较小的应用场景中,依然具有一定的适用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值