Mark&Sweep GC

 

 

    标记清除算法是第一个能够回收循环数据结构的算法。现在最普遍的垃圾回收技术都是标记清除算法的变体。当使用标记清除算法,没有被引用的对象不会被立即回收。相反,垃圾回收器允许先累计一些没有任何引用的对象 到一定程度(比如内存不足时),然后启动回收。在回收过程中,执行的程序会被临时挂起一旦回收结束,程序又能恢复执行。

   标记清除算法又称为 根跟踪算法root tracing . JVM 中,GC Roots 包括:

   A:VM 栈中,由本地变量引用的对象。

   B:在方法去中的静态引用。

   C:JNI(即native 方法)中的引用

   从上述Roots 开始,能够访问到的对象称为LIVE 对象,访问不到的对象称为not live.标记清除算法包含两个阶段: 阶段1:找到并标记所有可以访问的对象,这个阶段称之为标记阶段。阶段2gc在整个堆中扫描并回收所有没有被标记的对象,这个阶段称之为清除阶段。

   为了将活跃对象和垃圾对象给区分开来,我们在对象中记录了对象的状态,在每个Object 中添加一个字段marked,默认值为false. 当对象创建时候,所有的对象的marked 都是false,也就是未标记的。

  标记算法的伪代码:

  void mark (Object p)

if (!p.marked)

 p.marked = true;

        for each Object q referenced by p

            mark (q);

 

 当一个对象已经被标记过后,上述的递归算法就什么也不做,因而这也能保证递归能够顺利结束。 当所有可以访问的对象都被标记上了后,上述方法就会终止。

 清除算法的伪代码如下:

 void sweep ()

for each Object p in the heap

 if (p.marked)

       p.marked = false

  else

  heap.release (p);

 在清除阶段,为了找出未被标记的对象,gc算法需要在整个heap中扫描所有的对象。在扫描过程中,那些未被标记的对象的空间就会被回收,同时在每个live对象中的marked也会被设置回false以便下次gc. 如下图所示:

 a显示了gc开始的条件,在此例子中,只有一个root变量。

  b显示了标记阶段的效果,在此阶段,所有活跃对象就已经被标记了。最后,

  C 显示了清除阶段完成留下的对象。在内存中,只有活跃对象保留了并且这个对象的marked字段都被重置为false.

 


 

标记清除算法的优点:

<!--[if !supportLists]-->1.       <!--[endif]-->能够正确标记并回收垃圾,即使对于循环引用来说,也没有问题。

<!--[if !supportLists]-->2.       <!--[endif]-->对引用变量的操作没有任何开销

标记清除算法的缺点:

   1.导致应用程序挂起,对于那些有实时性约束的系统会带来一点问题。

 

标记清除算法引起的 碎片问题

 

   碎片问题是在经历了好几次gc之后发生的现象。这个问题是在对中的对象容易变得比较分散,Live 的对象被一些小的没有分配的内存区域互相隔开来。 问题是,在某些情况下,即使实际上有足够的没有使用的内存,但是这些内存是不连续的, 由于对象通常占用连续的存储单元,,因此就变得有可能不能为一个对象分配空间.

 标记清除算法不能标记出碎片,即使回收了所有垃圾对象的存储空间,堆可能会有太多的碎片而不能分配所需要的空间。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值