一、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內存嗎?有什么辦法主動通知虛擬機進行垃圾回收?
1、對於GC來說,當程序員創建對象時,GC就開始監控這個對象的地址、大小以及使用情況。
通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對象。通過這種方式確定哪些對象是"可達的",哪些對象是"不可達的"。當GC確定一些對象為"不可達"時,GC就有責任回收這些內存空間。
2、可以。程序員可以手動執行System.gc(),通知GC運行,但是Java語言規范並不保證GC一定會執行。
二、這里我們詳細了解一下System.gc()的工作原理:
Java中的內存分配是隨着new一個新的對象來實現的,這個很簡單,而且也還是有一些可以“改進”內存回收的機制的,其中最顯眼的就是這個System.gc()函數。
乍一看這個函數似乎是可以進行垃圾回收的,可事實並不是那么簡單。
其實這個gc()函數的作用只是提醒虛擬機:程序員希望進行一次垃圾回收。但是它不能保證垃圾回收一定會進行,而且具體什么時候進行是取決於具體的虛擬機的,不同的虛擬機有不同的對策。
那么下一個問題就是:gc()進行回收的准則是什么?也就是說什么樣的對象可以被回收?
簡單來說就是:沒有被任何可達變量指向的對象。這里的可達是我發明的……意思就是能夠找到的,那什么樣的是不可達的呢?
比如說:
1 a.v = b; 2 b.v = c; 3 /* 4 *Watch out ! 5 */ 6 a.v = d;
看一下這段代碼:
第一行:對象a的變量v指向了對象b
第二行:對象b的變量v指向了對象c
第六行:對象a的變量v指向了變量d。
這個時候,雖然變量c指向的對象有c以及b.v指向它,但是它們都已經不可達了,為什么?因為唯一可以找到它們的是a.v,但是現在a.v指向了d,所以他們就是不可達的了。
理由也很直觀:沒有任何可達變量指向你,你還有活下去的理由嗎?你就算活下去誰能找得到你呢?
所以說,C++中將釋放了的指針置為null的習慣要保留到Java中,因為這有可能是你釋放內存的唯一途徑。
最后的箴言:不要頻繁使用gc函數。
我的建議是:保持代碼健壯(記得將不用的變量置為null),讓虛擬機去管理內存。