????????Java虛擬機(JVM)使用垃圾收集器(Garbage Collector)來管理內存,清理不再使用的對象以釋放內存空間。垃圾收集的主要目標是自動化內存管理,使開發人員無需顯式地釋放不再使用的內存,從而降低了內存泄漏的風險。
JVM中垃圾收集的一般過程:
對象創建:
????????當應用程序創建新對象時,內存分配器負責為應用程序中使用的新對象分配內存空間。當應用程序需要創建一個新對象時,它會向內存分配器發出請求,請求分配一定大小的內存空間。內存分配器會檢查可用的內存空間,并為該請求分配合適的大小的空間。通常,內存分配器會分配連續的內存空間,并返回該空間的起始地址。
引用追蹤:
????????垃圾收集器通過引用追蹤算法來識別和收集不再使用的內存對象,以便回收內存空間。引用追蹤算法基于一個簡單的假設:當一個對象可以被訪問時,它就不是垃圾。因此,垃圾收集器需要追蹤哪些對象是可以被訪問的,以及哪些對象是不可訪問的。
????????垃圾收集器通過根集來開始引用追蹤。根集包括全局變量、靜態變量和調用棧中的指針等,它們是程序中始終可訪問的對象。垃圾收集器從根集開始,遞歸地遍歷所有可訪問對象,標記為可訪問的對象,并將不可訪問的對象標記為垃圾。
標記階段:
????????在引用追蹤過程中,垃圾收集器標記所有可達的對象。一般有三種主要的標記算法:標記-清除、標記-復制和標記-整理算法。
-
標記-清除算法:
????????如它的名字一樣,算法分為“標記”和“清除”兩個階段:首先標記出所有需要回收的對象,在標記完成后,統一回收掉所有被標記的對象,也可以反過來,標記存活的對象,統一回收所有未被標記的對象。這種算法可能會導致內存碎片化,影響性能。
-
標記-復制算法:
????????為了解決標記-清除算法面對大量可回收對象時執行效率低的問題,1969年Fenichel提出了一種稱為“半區復制”(Semispace Copying)的垃圾收集法,它將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然后再把已使用過的內存空間一次清理掉。這種方式減少了內存碎片,但是需要額外的空間。
-
標記-整理算法:
標記-整理算法的標記過程仍然與“標記-清除”算法一樣,但后續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向內存空間一端移動,然后直接清理掉邊界以外的內存。這也有助于減少內存碎片。
清理階段:
????????垃圾收集器在標記階段之后,對被標記為垃圾的對象進行回收和內存釋放的過程。
內存整理:
????????在清理階段之后,對于某些垃圾收集算法,可能需要進行內存整理,以便將存活對象集中在一起,減少碎片化。這一步通常涉及移動對象的位置。