## **什么是垃圾回收機制**
垃圾收集GC(Garbage Collection)是Java語言的核心技術之一,編程人員不需要去關心內存動態分配和垃圾回收的問題,這一切都交給了JVM來處理。可通過調用`System.gc`方法來"建議"執行垃圾收集器,但其是否可以執行,什么時候執行卻都是不可知的。
## **垃圾回收主要回收哪塊內存區域**
Java內存運行時內存結構中**程序計數器**、**虛擬機棧**、**本地方法棧**3個區域隨著線程的生存而生存的。內存分配和回收都是確定的。隨著線程的結束內存自然就被回收了,因此不需要考慮垃圾回收的問題。而Java**堆**則是由各線程共享,內存的分配和回收都是動態的。因此垃圾收集器所關注的都是這部分內存。
## **垃圾回收的對象**
如果這個對象沒有被其他對象所引用那么該對象就是無用的或者說不可達的,就會被回收。
## **如何判斷對象是否被引用**
采用**根搜索算法**的基本思路就是通過一系列名為”GC Roots”的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的。
GCRoots的對象包括下面幾種:
* 虛擬機棧(棧幀中的局部變量表)中引用的對象
* 堆(JDK8)/方法區(JDK6)中的類靜態屬性引用的對象。
* 常量池中常量引用的對象
* 本地方法棧中JNI(Native方法)引用的對象

## **垃圾回收機制策略**
GC在識別到可回收資源后會根據不同的算法進行回收,主要使用以下四個算法。
* 標記清除算法
* 復制算法
* 標記壓縮算法
* 分代算法
#### **標記清除算法**
該算法有2個階段
1. 標記:找到所有可訪問的對象,做個標記
2. 清除:遍歷堆,把未標識的對象回收
缺點:
1. 回收時,應用需要掛起
2. 標記和清除都需要遍歷堆,效率低
3. 定點清除會形成很多不連續的內存空間,造成內存碎片化。
#### **標記壓縮算法**
標記壓縮算法和標記清除算法很像,但是他提供了解決內存碎片化的方案。
* 任意順序 : 即不考慮原先對象的排列順序,也不考慮對象之間的引用關系,隨意移動對象
* 線性順序 : 考慮對象的引用關系,例如a對象引用了b對象,則盡可能將a和b移動到一塊
* 滑動順序 : 按照對象原來在堆中的順序滑動到堆的一端
缺點:缺點壓縮階段,由于移動了可用對象,需要去更新引用
#### **復制算法**
堆中內存模型主要包含:Eden、From、To、老年代。對象在堆中的存儲流
1. 新創建的對象存入Eden、當Eden滿時會觸發一次young gc,把還活著的對象copy到From區,然后清空Eden區域。
2. Eden再次觸發young gc時,會掃描Eden區和From區,把活著的對象copy到To區,然后清空Eden和From區域。
3. Eden再次觸發young gc時,會掃描Eden區和To區,把活著的對象copy到From區,然后清空Eden和To區域。
4. 部分對象會在From和To區域中復制來復制去,如此交換15次(由JVM參數MaxTenuringThreshold決定,這個參數默認是15),最終如果還是存活,就存入到老年代。
優點:對真塊區域進行清除、性能高,同時可以解決內存碎片化問題。
缺點:From和To區實際是2塊一樣的內存空間,會造成一定的內存浪費。
#### **分代算法**
JVM根據新生代和老年代的特點采用不同的收集算法
1. 新生代中,每次進行垃圾回收都會發現大量對象死去,只有少量存活,因此比較適合復制算法。只需要付出少量存活對象的復制成本就可以完成收集。
2. 老年代中,因為對象存活率較高,沒有額外的空間進行分配擔保,所以適合標記-清理、標記-整理算法來進行回收。
## **Minor GC和Full GC**
**Minor GC**
概念:新生代的垃圾回收、比較頻繁、回收速度快。
觸發機制:Eden區滿時會觸發Minor GC.
**Full GC**
概念:老年代的垃圾回收、速度比Minor GC 慢很多。
觸發機制:當年老代滿時會引發FullGC,FullGC將會同時回收年輕代、年老代。通常一次FUll GC會伴隨至少一次的MinorGC。