国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

怎樣處理Java最終化的內存保留問題

2019-11-18 11:06:35
字體:
來源:轉載
供稿:網友


  最終化答應實現java對象的最后清理;但是,就算不顯式地使用它,它也能延遲資源的回收。在本文中你還會學習如何避免類似的內存保留問題。

  一、 引言

  最終化是Java編程語言的一個特性:它答應你對垃圾收集器發現的不可達的對象進行最后清理。典型地用于回收與一對象相關聯的本地資源。下面是一個簡單的最終化示例:

public class Image1 {
 //指向本地圖像數據
 PRivate int nativeImg;
 private Point pos;
 private Dimension dim;
 //它釋放本地圖像;
 //隨后對它的調用將被忽略
 private native void disposeNative();
 public void dispose() { disposeNative(); }
 protected void finalize() { dispose(); }
 static private Image1 randomImg;
}
怎樣處理Java最終化的內存保留問題(圖一)
圖1.一個可最終化的對象

  有時,在一個Image1實例變為不可達的時,Java虛擬機(JVM)將調用它的finalize()方法來確保含有圖像數據(在本例中被整數nativeImg所指向)的本地資源已經被回收。然而,請注重,該finalize()方法,先不管它被JVM進行專門對待,是一個任意的方法-它包含任意的代碼。非凡地,它能存取任何對象中的任何字段(在本例中指pos和dim)。令人驚奇的是,它還能使該對象再次成為可達的-比如說通過讓它從一個靜態字段成為可達的(如,randomImg=this;)。我根本不推薦使用后面這種編程實踐,但是遺憾的是,Java編程語言答應它。

  下面步驟描述一個可最終化的對象obj的生命周期-也即,這是一個其類中有一個非平凡的(non-trivial)終結器的對象(見圖1):

怎樣處理Java最終化的內存保留問題(圖二)
圖2.垃圾收集器確定這個obj是不可達的

  1. 當obj被分配時,JVM內部地記錄下這個obj是可最終化的(這在典型情況下會減慢現代JVM具有的其它方面的分配路徑)。

  2. 當垃圾收集器確定該obj是不可達的時,它注重到,這個obj是可最終化的(因為它在分配時就被記錄下來)并且把它添加到JVM的最終化隊列上。它還確保從obj可達的所有對象被保留起來,即使它們從其它對象也許是不可達的,因為它們可能會被終結器所存取。圖2展示了Image1的一個實例的情況。

  3. 在后面的時候,JVM的終結器線程將出隊obj,調用它的finalize()方法,并且記錄下該obj的終結器已經被調用。此時,obj被認為是被最終化的。

  4. 當垃圾收集器再次發現該obj是不可達的時,它將連同一切它所可達的(假定后者是不可達的)對象回收它的空間。

  注重,垃圾收集器至少需要兩個周期(也許更多)往返收obj并且需要保留在該過程中所有另外的從obj可達的對象。假如一個程序員不小心,那么這可能會創建暫時的、微妙的和無法預言的資源保留問題。另外,JVM并不保證它將調用所有的已分配的可最終化的對象的終結器;它可能在垃圾收集器發現它們其中一些是不可達的之前就已退出。

二、 在子類化時避免內存保留問題

  就算你不顯式地使用它,最終化也可能延期資源的回收。請考慮下列實例:

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();}
}
怎樣處理Java最終化的內存保留問題(圖三)
圖3.GC將因最終化而只排隊Image1實例

  與RGBImage1相比,RGBImage2包含一個Image1的實例而不是擴展Image1。當RGBImage2的一個實例成為不可達時,垃圾回收器將即時回收它,連同rgbData數組(假定后者從任何其它地方都是不可達的),并且在最終化時將只排隊Image1實例(見圖4)。既然類RGBImage2并沒有子類化Image1,那么它就不會從它中繼續任何方法。因此,你可能必須把delegator方法添加到RGBImage1以存取要求的Image1中的方法(dispose()方法就是這樣的一個例子)。

  然而,你不可能總是用上面描述的方式重新安排你的代碼。在這種情況下,作為一個類用戶,你必須做點多余的工作來確保當它們被終結時其實例并不占有多余的空間。下列代碼說明實現方法:



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 闻喜县| 绥阳县| 临高县| 平凉市| 河南省| 哈巴河县| 中方县| 曲靖市| 恩平市| 通化市| 东乌珠穆沁旗| 竹溪县| 金寨县| 道真| 古蔺县| 雷州市| 察隅县| 新干县| 静乐县| 秭归县| 阿坝县| 寿阳县| 上虞市| 揭阳市| 德令哈市| 嘉兴市| 项城市| 和平区| 虎林市| 当涂县| 建昌县| 利辛县| 永新县| 武强县| 平定县| 格尔木市| 盐城市| 泸水县| 泗洪县| 会同县| 曲周县|