java 中System.gc和finalize方法

1.finalize()介紹

finalize()是Object的protected方法,子類可以覆蓋該方法以實現資源清理工作,GC在回收對象之前調用該方法。

finalize()與C++中的析構函數不是對應的,但Java中的finalize的調用具有不確定性。

finalize方法在垃圾回收器準備垃圾回收前被調用,但是不一定會被調用

finalize()其實是用來釋放不是通過java的new關鍵字分配的內存,比如說通過本地方法調用了c程序,該c程序malloc分配了內存,那麼垃圾回收器就不能通過java語言來釋放內存,只能在finalize方法內通過本地方法調用c程序進行釋放內存。

2.finalize()的執行過程

一個對象真正死亡,至少要經歷兩次標記過程:如果對象不可達,那它將會被第一次標記並且進行一次篩選。篩選的條件是此對象是否需要執行finalize()方法。當對象沒有覆蓋finalize()方法,或者finalize()方法已經被虛擬機調用過,虛擬機將這兩種情況都視為“沒有必要執行”。

如果對象被判定為有必要執行finalize()方法,會放置在F-Queue的隊列之中,並稍後由一個由虛擬機自動建立的、低優先級的Finalizer線程去執行。這裡所謂的“執行”是指虛擬機會觸發這個方法,但並不承諾會等待它運行結束,原因是如果一個對象在finalize()方法中執行緩慢,或者發生了死循環,可能會導致F-Queue隊列中其他對象永久處於等待,甚至導致整個內存回收系統崩潰。

finalize()方法是對象逃脫死亡命運的最後一次機會,稍後GC將對F-Queue中的對象進行第二次小規模的標記,如果對象要在finalize()中成功拯救自己——只要重新與引用鏈上的任何一個對象建立關聯即可,譬如把自己(this關鍵字)賦值給某個類變量或者對象的成員變量,那麼在第二次標記時它將被移除出“即將回收”的集合;如果對象這時候還沒有逃脫,那麼基本上它就真的被回收了。

總結:finalize()並不是必須要執行的,它只能執行一次或者0次。如果在finalize中建立對象關聯,則當前對象可以復活一次。

3.finalize()方法發生調用的情況

所有對象被Garbage Collection時自動調用,比如運行System.gc()的時候;

程序退出時為每個對象調用一次finalize方法;

顯式的調用finalize方法

除此以外,正常情況下,當某個對象被系統收集為無用信息的時候,finalize()將被自動調用,但是jvm不保證finalize()一定被調用。

4.System.gc()方法

System.gc()建議垃圾回收器進行垃圾回收,但是不一會立即執行,不管新的對象還是舊的對象都會進行回收,是full gc

system.gc其實是做一次full gc

system.gc會暫停整個進程

system.gc一般情況下我們要禁掉,使用-XX:+DisableExplicitGC

system.gc在cms gc下我們通過-XX:+ExplicitGCInvokesConcurrent來做一次稍微高效點的GC(效果比Full GC要好些)

system.gc最常見的場景是RMI/NIO下的堆外內存分配等。


分享到:


相關文章: