码迷,mamicode.com
首页 > 其他好文 > 详细

第九节:对象复活

时间:2015-04-21 20:33:01      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

前面“终结操作解密”讲过,需要终结一个对象被认为死亡时,垃圾回收器会强制对象重生,使它的Finalize方法得以调用。Finalize方法调用之后,对象才真正死亡。总之,需要终结的一个对象会经历死亡、重生、再死亡的“三部曲”。一个死亡的对象重生的过程称为复活。

准备调用对象的Finalize方法,这是复活的一种形式。垃圾回收器将一个对象引用放入freachable队列时,对象就从根可达,得以复活。这是必须的,因为只有这样,Finalize方法中的代码才能访问对象的字段。最终,对象的Finalize方法返回,不再有任何根指向对象(因为对象已从freachable队列中移除),对象宣布真正死亡。

但是,如下代码所示,如果Finalize方法在执行时将指向这个对象的指针放到一个静态字段中,又会怎样?

Calss  SomeType

{

      ~SomeType()

{

Program. s_objHolder=this;

}

}

Static class program

{

 Public static object  s_objHolder;

}

在本例中,当SomeType对象的Finalize方法被调用时,对该对象的引用被放入了一个根,使对象从应用程序的代码中可达。对象现在就复活了,垃圾回收期不再认为它是垃圾。应用程序可自由使用该对象。但必须记住的是,该对象曾被终结,所以使用它可能造成无法预测的后果,另外还要注意,如果SomeType的一些字段引用了其他对象,所有的对象都会复活,因为他们都从应用程序 根可达。但请注意,在这些对象中,一部分对象的Finalize方法可能已经调用过。

复活一般不是一件好事,应避免写代码来使用CLR这个功能。只有在应用程序的体系结构要求反复使用同一个对象时,复活才有用处。在这种情况下,当对象使用完毕时,会发生垃圾回收。在对象的Finalize方法中,它将它的this指针赋给另一个根,阻止对象死亡。但是,你想告诉垃圾回收器在下一次使用之后,再次调用Finalize方法,为此,GC类提供了一个ReRegisterForFinalize的静态方法,该方法只有一个参数,也就是对象引用,

 

Calss  SomeType

{

      ~SomeType()

{

Program. s_objHolder=this;

GC. ReRegisterForFinalize(this);

}

}

Finalize方法被调用时,它让一个根引用对象,从而时对象复活。然后,Finalize方法调用ReRegisterForFinalize,后者将指定对象的指针添加到终结者列表末尾。当垃圾回收器判断这个对象不可达时(未来在某个时刻,当静态字段为null),他会将对象的指针从终结者列表移到freachable队列,造成对象的Finalize方法被再次调用。记住,复活一个对象,将复活该对象引用的所有对象,可能需要为所有这些对象调用ReRegisterForFinalize,但大多数情况下都不可能是这样做,因为无权访问其他对象的私有字段。

这个例子演示了如何创建一个不断复活,永远死不了的对象,但是一般都不希望对象有这样的行为。更常见的做法实在Finalize方法中条件性的设置一个根来引用对象。

注意 :要保证每一次复活时,都的调用ReRegisterForFinalize方法一次,否则对象的Finalize方法会被调用多次,这是因为每调用一次ReRegisterForFinalize方法,都会在终结列表中追加一条记录项。对象被判断为垃圾后,所有这些记录项都被移到freachable队列中,导致对象的Finalize方法被多次调用。

 

第九节:对象复活

标签:

原文地址:http://www.cnblogs.com/bingbinggui/p/4445191.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!