乍一看,垃圾收集應該處理名稱所暗示的內容——查找和丟棄垃圾。實際上,它所作的偏偏相反:垃圾收集跟蹤全部仍在使用的對象,並將其他對象標記爲垃圾。有了這個概念,咱們開始深刻研究Java虛擬機(JVM)垃圾收集(GC)所涉及自動內存回收的相關細節。c++
學過C/C++的都知道,您必須手動並顯式地爲數據分配和釋放內存。若是忘記釋放它,你將沒法重用內存,這些內存將被聲明但再也不被使用。這種狀況稱爲內存泄漏。程序員
下面是個C語言的示例:算法
int send_request() {
size_t n = read_size();
int *elements = malloc(n * sizeof(int));
if(read_elements(n, elements) < n) {
// elements not freed!
return -1;
}
// …
free(elements)
return 0;
}
複製代碼
如上文所示,很容易忘記釋放內存。內存泄漏是一個很困擾開發者的問題。你只能經過修改你的代碼來修復它們,可是在大型系統中,這將變得十分困難。所以,更好的方法是自動回收未使用的內存,徹底消除人爲出錯的可能性。這種自動化稱爲垃圾收集(簡稱GC)。編程
第一個自動化這種過程的方法是使用析構函數。例如,咱們能夠在c++中使用vector作一樣的事情,當析構函數不在做用域中時,它將被自動調用:緩存
int send_request() {
size_t n = read_size();
vector<int> elements = vector<int>(n);
if(read_elements(elements.size(), &elements[0]) < n) {
return -1;
}
return 0;
}
複製代碼
可是在更復雜的狀況下,特別是在多個線程共享對象時,僅使用析構函數是不夠的。解決的辦法是:引用計數(reference counting):對於每一個對象,您只需知道它被引用了多少次,以及當這個計數達到零時,能夠安全地回收該對象。一個著名的例子就是c++的共享指針:安全
int send_request() {
size_t n = read_size();
auto elements = make_shared<vector<int>>();
// read elements
store_in_cache(elements);
// process elements further
return 0;
}
複製代碼
爲了不在下次調用函數時讀取元素,咱們可能須要緩存它們。在這種狀況下,在向量超出範圍時銷燬它不是一個選項。所以,咱們使用shared_ptr。它跟蹤對它的引用的數量。這個數字隨着您傳遞它而增長,隨着它離開範圍而減小。一旦引用的數量達到零,shared_ptr就會自動刪除底層向量。bash
在上面的c++代碼中,咱們仍然須要明確地指出什麼時候須要進行內存管理。但若是咱們能讓全部對象都這樣呢?這將很是方便,開發人員再也不須要考慮本身清理以後的問題。程序運行時將自動理解再也不使用的某些內存並釋放它。換句話說,它自動收集垃圾。第一個垃圾收集器是在1959年爲Lisp建立的,從那時起該技術纔開始發展。編程語言
咱們用c++的共享指針演示的思想能夠應用於全部對象。許多語言,如Perl、Python或PHP都採用這種方法。以下圖:函數
綠色的表示它們所指向的對象仍然在被程序員使用。從技術上講,這些多是當前執行方法中的局部變量或靜態變量或其餘東西。它可能會因編程語言的不一樣而有所不一樣,因此咱們不在這裏集中討論它。藍色圓圈是內存中的活動對象,其中的數字表示它們的引用計數。ui
最後,灰色圓圈是未從任何仍顯式使用的對象引用的對象(這些對象由綠色雲直接引用)。
看到了嗎?紅色對象其實是應用程序不使用的垃圾。可是因爲引用計數的限制,仍然存在內存泄漏。
有一些方法能夠克服這個問題,好比使用特殊的「弱」引用或應用一個單獨的算法來收集循環。前面提到的語言——Perl、Python和PHP——都以這樣或那樣的方式處理循環,但這超出了本手冊的範圍。相反,咱們將開始更詳細地研究JVM採用的方法。
首先,JVM對對象的可達性的構成更加具體。與咱們在前幾章中看到的模糊定義的綠雲不一樣,咱們有一組很是具體和明確的對象,稱爲GC Roots:
JVM跟蹤全部可訪問(活動)對象,並確保不可訪問對象聲明的內存能夠重用的方法稱爲標記和清除算法。它包括兩步:
JVM中不一樣的GC算法(如並行清除、CMS)實現這些標記+清除的方式略有不一樣,可是在概念相似。
這種方法相當重要的一點是,環形引用再也不泄露:
不太好的一點是,爲了垃圾回收的進行,應用程序線程須要中止:由於若是引用一直在更改,對象就無法真正計數。當應用程序暫時中止,以便JVM能夠專一於垃圾回收時,這種狀況稱爲「Stop The Word」(STW)。STW發生的緣由有不少,可是垃圾收集是目前最流行的一種。