正 文

怎样处理Java最终化的内存保留问题


www.7dspace.com  更新日期:2006-3-1 5:52:10  七度空间


  二、在子类化时避免内存保留问题

  就算你不显式地使用它,最终化也可能延期资源的回收。请考虑下列实例:

public class RGBImage1 extends Image1 {
 private byte rgbData[];
}

  RGBImage1扩展Image1并且引入了新字段rgbData(也许还有一些方法,而本示例中却没有显示)。尽管你没有显式地在 RGBImage1上定义一终结器,但是,这个类将自然地继承Image1的finalize()方法,并且所有的RGBImage1实例也将被认为是可最终化的。当一个RGBImage1实例成为不可达的,回收可能的很大的rgbData数组将被延迟直到该实例被终结(见图3)。这可能是一个很难发现的问题,因为该终结器可能是隐藏在一个很深的类层次上。

  一种避免这个问题的方法是重新安排代码,这样它可以使用"包含"来代替"扩展"模式,如下所示:

public class RGBImage2 {
 private Image1 img;
 private byte rgbData[];
 public void dispose() {img.dispose();}
}


图3.GC将因最终化而只排队Image1实例

  与RGBImage1相比,RGBImage2包含一个Image1的实例而不是扩展Image1。当RGBImage2的一个实例成为不可达时,垃圾回收器将即时回收它,连同rgbData数组(假定后者从任何其它地方都是不可达的),并且在最终化时将只排队Image1实例(见图4)。既然类 RGBImage2并没有子类化Image1,那么它就不会从它中继承任何方法。因此,你可能必须把delegator方法添加到RGBImage1以存取要求的Image1中的方法(dispose()方法就是这样的一个例子)。

  然而,你不可能总是用上面描述的方式重新安排你的代码。在这种情况下,作为一个类用户,你必须做点多余的工作来确保当它们被终结时其实例并不占有多余的空间。下列代码说明实现方法:

public class RGBImage3 extends Image1 {
 private byte rgbData[];
 public void dispose() {
  super.dispose();
  rgbData = null;
 }
}


图4.在使用一个RGBImage3实例后调用dispose()

  RGBImage3与RGBImage1相同,但是添加了dispose()方法-它用来把rgbData字段置为null。你需要显式地在使用完一个 RGBImage3实例之后调用dispose()以保证rgbData数组被即时回收(见图4)。我推荐在极少的场合下显式地把字段置为null;这里就是其中之一。
4页,页码:[1] [2] [3] [4] 

上一篇:超强恶搞 玩不崩溃的Firefox
下一篇:CorelDRAW制作胶片底片相框
怎样处理Java最终化的内存保留问题 作者:朱先忠编译 来源:天极网
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐