| 1 Java有個東西叫垃圾收集器,它讓建立的對象不需要像c/cpp那樣delete、free掉,你能不能談談,GC是在什麼時候,對什麼東西,做了什麼事情。 |
一,如何gc。 GC是在是一個獨立的線程,用來操作堆記憶體。 Garbage Collection 是根據分代來收集:對年輕代的收集和對老年代的收集; 年輕代又稱為eden s0 s1(Survive代) 代,老年代又稱為tenured代;年輕代滿了的化採用minor gc 他採用的是一種複製演算法,就是,預先分配兩塊相同的空間,只使用其中的一塊,當這塊空間滿的話,會觸發morror gc ,通過root節點,先標記所有可達的點,然後再進行copy可達的點,到另一塊空間,然後再釋放原先的空間的節點。(可以減少記憶體片段) 老年代滿了則採用full gc,當老年代的對象大於老年代剩餘的對象的時候,此時,會觸發full gc; 老年代的對象一般都是比較大,直接採用的是標記-刪除演算法; 當gc逾時的時候就會觸發OOM;可以設定新生代和老年代的比例來進行對的記憶體最佳化; |
二,什麼時候對象會被GC。 根據跟搜尋演算法,從roots開始尋找,如果對象不可達,對象會被GC(對象到GC roots沒有任何引用鏈),還有一種演算法:引用計數法,他不能很好的解決循環參考問題。(python採用的是這種機制) |
JVM將堆分成了 二個大區 Young 和 Old 如下圖:
而Young 區又分為 Eden、Servivor1、Servivor2, 兩個Survivor 區相對地作為為From 和 To 邏輯地區, 當Servivor1作為 From 時 , Servivor2 就作為 To, 反之亦然
如下圖:
因此當Eden區滿的時候 GC執行,這時會將 Eden 區和 From 區中還被引用的對象會被移到 To區 ,個別大對象和部分From對象在To已滿的情況下會被放到Old區,如下圖:
GC操作執行完之後 Eden和 From 區將會為空白(無引用對象被回收,有引用對象被移到To和Old區) ,並且From 和 To在邏輯上的 概念調換 , From 概念上變成了To,To變成了From(如果Servior1 原來作為 From 區 ,現在Servior1 現在就作為 To 區),GC執行後結果如下圖:
HotSpot VM 記憶體堆的兩個Servivor區 。在原始的copying收集演算法裡,空間被分為兩半,叫做semispace。空間分配和回收的過程就是把其中一半用作from來分配空間,當from快滿或滿足別的一些條件時將可到達的對象複製到to,並將from與to邏輯交換的過程。
單純的copying收集不能很好的應對長時間存活的對象,因為那樣的對象每次經曆收集的時候都還活著,帶來拷貝的開銷。出於權衡,HotSpot裡目前除G1外都採用相似的方式實現分代式GC,並且在young gen都使用copying收集演算法。不過它使用的copying演算法是原始演算法的變種,留一塊較大的地區作為eden,在eden與old gen之間設定semispace來作為緩衝,讓“中等壽命”的對象盡量在進入old gen之前被收集掉。這就是HotSpot的survivor spaces了。