導論:
- 將一個對象初始化後就“棄之不顧”的做法並非總是安全的。雖然java用垃圾回收器回收無用對象佔用的內存資源。但也有特殊情況,
假定對象並非使用new獲得了一塊“特殊”的區域,由於垃圾回收器只知道釋放那些經由new分配的內存,所以他不知道該怎樣釋
放這塊“特殊”的內存。
1.finalize()
- 此方法出現的原因:回收除以new方法創建對象方式以外的方式分配的內存
- 爲了應對上面的那種情況,java允許在類中定義一個名爲finalize()的方法。
- 工作原理:一旦垃圾回收器準備好釋放對象佔用的存儲空間,將首先調用其finalize()方法,並且在下一次垃圾回收動作發生時,纔會真正回收對象佔用的內存。
- 潛在編程陷阱:
對象可能不被垃圾回收
垃圾回收並不等於“析構” - 只要程序沒有瀕臨存儲空間用完的那一刻,對象佔用的空間就總也得不到釋放。如果程序結束,並且對象佔用的存儲空間一直沒有被垃圾回收器回收,則會隨着
程序的退出,那些資源也會全部交還給操作系統。 - 之所以使用finalize()方法,大多數是發生在使用“本地方法c”的情況下。
所以不要過多的調用finalize()方法。它是處理特殊情況的清理工作的。
垃圾回收並不能完全代替析構函數,如果想進行出釋放存儲空間之外的清理工作,還是得明確的調用某個恰當的Java方法。
無論是垃圾回收還是終結,都不保證一定發生。如果Java虛擬機並未面臨內存耗盡時,它是不會浪費時間去執行垃圾回收以回覆內存的。
- 只要程序中存在沒有被適當清理的部分,程序就存在很隱晦的缺陷。使用finalize()方法發現這種缺陷。因爲他總是在對象被回收前調用。
2.垃圾回收器是如何工作的
- 垃圾回收器對於提高對象的創建速度,有明顯的效果
- 存儲空間的釋放會影響存儲空間的分配?這確實java虛擬機的工作方式。
- 在某些java虛擬機上:堆的分配更像一個傳送帶,每分配一個新對象,他就往前移動一個。這意味着分配的速度非常快。java“堆指針”只是簡單的移動到尚未分配的區域,效率非常高。
然而,實際上java中的堆未必完全像傳送帶那樣工作。要是真的那樣的話,勢必會導致頻繁的內存頁面調度——將其移進移出硬盤。頁面的調度會顯著的影響性能,最終,在創建了足
夠多的對象後,內存資源將耗盡。
解決的方法就是垃圾回收器,當它工作時,將一面回收空間,一面使堆中的對象緊湊排列,這樣“堆指針”就可以很容易移動到更靠近傳送帶的開始出,也就避免了頁面錯誤的調度。 - 通過垃圾回收器對對象重新排列,實現了一種高速的、有無限空間可供分配的對模型。
3.其他系統中的垃圾回收機制【第90頁】
- 引用計數模式
- 自適應垃圾回收技術
- 複製式回收器
- 標記-清掃
- 停止-複製
- 及時編譯計數
- ······還有好多(或許自己也可以創造出來一種)