關於垃圾回收,主要是兩個步驟:
那麼,哪些對象可以被認為是“GC Roots”對象呢,如下
先來看下垃圾回收的三種算法
將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然後再把已使用過的內存空間一次清理掉。
首先標記出所有需要回收的對象,在標記完成後統一回收所有被標記的對象;
它主要有兩個不足:一個是效率問題,標記和清除兩個過程的效率都不高;另一個是空間問題,標記清除之後會產生大量不連續的內存碎片;
標記過程仍然與“標記-清除”算法一樣,但後續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然後直接清理掉端邊界以外的內存。
那麼,垃圾對象是如何回收的呢?答案是分代回收。
不同的對象的生命周期是不一樣的。因此,不同生命周期的對象可以采取不同的收集方式,以便提高回收效率。分代垃圾回收采用分治的思想,進行代的劃分,把不同生命周期的對象放在不同代上,不同代上采用最適合它的垃圾回收方式進行回收。
一般,Java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當的收集算法。
在新生代中,有大批對象死去,只有少量存活,一般選用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。新生代分三個區。一個Eden區,兩個Survivor區(救助空間,一般而言)。大部分對象在Eden區中生成,當Eden區滿時,還存活的對象將被復制到Survivor區(兩個中的一個);新創建的對象的內存都分配自eden,Minor collection的過程就是將eden和在survivor space中的活對象copy到空閒survivor space中,對象在新生代裡經歷了一定次數(可以通過參數配置)的minor collection後,就會被移到老年代中,稱為tenuring。
老年代中因為對象存活率高,不需要大量清理或整理,因此使用“標記—清理”或者“標記—整理”算法來進行回收。
GC分為兩種,Scavenge GC和Full GC;
有如下原因可能導致Full GC:
參考:
《深入理解Java虛擬機》
http://blog.csdn.net/fenglibing/article/details/8928927