高效Java第六条消除过期的对象引用无意识的对象保持
問題的引出
這段程序有一個“內存泄露”,隨著GC活動的增加,或者由于內存占用的不斷增加,程序性能降低會逐漸表現出來。在極端的情況下,這種內存泄露會導致磁盤交換,甚至導致程序失敗(OutOfMemoryError),但是這種失敗情況相對比較少見。
內存泄露的地方:一個棧先是增長,然后再收縮,那么,從棧中彈出來的對象將不會被當做垃圾回收,即使使用棧的程序不再引用這些對象,它們也不會被回收。
棧內部維護著對這些對象的過期引用(永遠也不會再被解除的引用)。
elements數組中下標小于size的那些元素都是過期的。
無意識的對象保持導致的問題
在支持垃圾回收的語言中,內存泄露是很隱蔽的,無意識的對象保持。
一個對象引用被無意識地保留起來,那么,GC不僅不會處理這個對象,而且也不會處理這個對象所引用的所有其他對象,因此有可能會對性能造成潛在的重大影響。
無意識的對象保持修復方法
一旦對象引用已經過期,只需清空這些引用即可。
清空過期引用的另一個好處是,如果它們以后又被錯誤地解除引用,程序會立即拋出NullPointerException異常,而不是悄悄地錯誤運行下去。
清空對象引用應該是一種例外,而不是一種規范行為
清除過期引用最好的辦法是讓包含該引用的變量結束其生命周期。
清空引用的時機
Stack類自己管理內存。存儲池包含了elements數組的元素。數組活動區域中的元素是已分配的,而數組其余部分的元素則是自由的。但是GC并不知道這一點;對于GC而言,elements數組中的所有對象引用都同等有效。只有程序員知道數組的非活動部分是不重要的。程序員可以把這個情況告知GC:一旦數組元素變成了非活動部分的一部分,程序員就手工清空這些數組元素。
只要類是自己管理內存,程序員就應該警惕內存泄露問題。一旦元素被釋放掉,則該元素中包含的任何對象引用都應該被清空。
內存泄露的另一個常見來源是緩存
只要在緩存之外存在對某個項的鍵的引用,該項就有意義,那么就可以用WeakHashMap代表緩存;當緩存中的項過期之后,它們就會自動被刪除。記住只有當所要的緩存項的生命周期是由該鍵的外部引用而不是由值決定時,才有用處。
"緩存項的生命周期是否有意義"并不是很容易確定,隨著時間的推移,其中的項會變得越來越沒有價值。在這種情況下,緩存應該時不時地清理掉沒用的項。這項清除工作可以由一個后臺線程來完成,或在給緩存添加新條目的時候順便進行清理。
LinkedHashMap類可以使用removeEldestEntry()實現在給緩存添加新條目的時候進行清理。
對于更復雜的緩存,必須直接使用java.lang.ref。
內存泄露的第三個常見的來源是監聽器和其他回調。
客戶端在API中注冊回調,卻沒有顯示地取消注冊。
確保回調立即被當做垃圾回收的最佳方法是只保存它們的弱引用,例如,只將它們保存成中的鍵。
?為了讓學習變得輕松、高效,今天給大家免費分享一套Java教學資源。幫助大家在成為Java架構師的道路上披荊斬棘。需要資料的歡迎加入學習交流群:9285,05736
總結
以上是生活随笔為你收集整理的高效Java第六条消除过期的对象引用无意识的对象保持的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单片机c语言怎样添加自定义头文件,单片机
- 下一篇: Java开发学习必须了解的基础知识点