標籤:手動 分配 作用 單例 內容 翻譯 最簡 tsp ibm
Java記憶體回收手冊翻譯 - 什麼是記憶體回收
初看之下,記憶體回收應該要做其名稱之事 - 找到和丟掉垃圾。然而事實上它正好做著相反的事,記憶體回收會記錄所有仍在使用中的對象,然後將其他標記為垃圾。謹記這點,我們開始挖掘更多Java虛擬機器如何?被稱為記憶體回收的自動化記憶體回收過程的細節。
為了避免一頭紮進細節,我們從頭開始,解釋記憶體回收的一般性質以及核心概念和方法。
免責聲明:本手冊關注於Oracle Hotspot和OpenJDK的表現,其他運行時甚至其他虛擬機器,比如jRockit或IBM J9,會在某些方面有不同於本手冊所涵蓋的表現。
手動記憶體管理
在開始現代形式的記憶體回收內容之前,我們先快速回顧一下那些需要手動顯示分配和釋放資料記憶體的日子。那時候如果你忘記釋放記憶體,你將不能重用那塊記憶體。這部分記憶體會被聲明到但是沒有使用,這種情境叫做記憶體流失。
下面是一個用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;}
但是再更複雜的情況中,尤其是在多個線程中共用對象時,僅僅使用解構函式並不夠。這就引出了記憶體回收最簡單的形式:引用計數。對每個對象,你只需要知道它有多少次被引用到,並且當這個計數達到零時這個對象就可以安全的被回收。一個眾所周知的例子是C++中的共用指標shared pointers:
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;}
現在,為了避免下次函數調用時再去讀這個元素elements,我們可能想要緩衝他們。在這個例子中,就不能再當向量vector離開範圍時銷毀它。因此,我們使用共用指標shared_ptr,它記錄引用到它的數量,當你使用它傳值時計數增加,同時當它離開範圍時計數減少。一旦引用的計數降到零,共用指標shared_ptr就會自動地刪除下面的向量。
TBC...
Java記憶體回收手冊翻譯 - 什麼是記憶體回收