System.gc()
在默認情況下坊谁,執(zhí)行System.gc()會顯示的觸發(fā)FullGC锣披,同時對新生代以及老年大產(chǎn)生影響,進行回收糙申。
其實在正常情況下叨叙,垃圾回收都是自動進行的锭弊,無需人為主動觸發(fā),因為頻繁的觸發(fā)垃圾回收對整體系統(tǒng)來說時沒有好處的擂错,因此虛擬機會提供一個參數(shù)DisableExceptionGC來控制是否手工觸發(fā)GC的味滞。
我們可以看以下具體的實現(xiàn):
Runtime.getRuntime().gc();
內(nèi)部是一個native方法:
public native void gc();
我們可以看下C++源碼:
可以看到,其實是通過判斷DisableExplicitGC這個參數(shù)去判斷是否進行垃圾回收的钮呀,所以我們可以i設(shè)置: -XX:-+DisableExplicitGC,條件判斷就無法成立剑鞍,那么就會用顯示GC,使得System.gc等價于一個空函數(shù)調(diào)用行楞。
同時攒暇,當(dāng)我們使用System.gc的時候,如果垃圾回收器是CMS或者G1的話子房,默認是不會執(zhí)行并發(fā)的方式進行回收的,這時候我們需要打開虛擬機參數(shù):
-xx:+ExplicitGCInvokesConcurrent 該參數(shù)就轧,可以在使用CMS或者G1時证杭,如果觸發(fā)system.gc,會并發(fā)的執(zhí)行垃圾回收。
finalize對于垃圾回收的影響
在java中提供了一個類似C++析構(gòu)函數(shù)的機制===finalize
protected void finalize() throws Throwable { }
可以看到妒御,該方法設(shè)置成protected解愤,可以用于子類重寫,用于在對象倍回收時進行資源的釋放乎莉。
在目前送讲,普遍的認識是盡量不要使用finalize函數(shù)進行資源釋放,原因如下:
1.在finalize時可能會導(dǎo)致對象復(fù)活惋啃,在finalize函數(shù)執(zhí)行之前哼鬓,可能在系統(tǒng)中對象的引用已經(jīng)倍清楚了,但是作為實例方法finalize边灭,對象的this引用依然會被傳入方法內(nèi)部异希,如果引用外泄,對象就會復(fù)活绒瘦,此時對象又會變成可觸及狀態(tài)称簿。
2.finalize的執(zhí)行時間是不能保證的扣癣,完全由gc線程決定,因此極端情況下憨降,若不發(fā)生gc父虑,則將沒有己會執(zhí)行。推薦在try catch finally中釋放授药。
函數(shù)finalize是由FinalizerThread線程處理的频轿,每一個即將被回收的并且包含有finalize方法的對象都會在正式回收前加入FinalizerThread的執(zhí)行隊列,該隊列是引用隊列烁焙,內(nèi)部實現(xiàn)為鏈表結(jié)構(gòu)航邢。
Finalizer內(nèi)部封裝了實際的回收對象,referent字段則指向?qū)嶋H的對象引用骄蝇。
由于對象在回收之前被Finalizer的referent字段進行強引用膳殷,并加入了FinalizerThread的執(zhí)行隊列,這意味著對象又變?yōu)榭蛇_性對象九火,因此阻止了對象的正匙裕回收。
由于在引用對象中的元素排隊執(zhí)行finalize方法岔激,一旦出現(xiàn)性能問題勒极,將導(dǎo)致這些垃圾對象長時間堆積在內(nèi)存中,可能導(dǎo)致OOM異常虑鼎。
部分取材自: 《實戰(zhàn)java虛擬機》
《深入理解jvm虛擬機》