原文連接:https://blog.csdn.net/xiangzh...java
垃圾收集器通常完成兩件事算法
一般,Java對象的引用能夠分爲4類:強引用、軟引用、弱引用和虛引用。.net
強引用:一般能夠認爲是經過new出來的對象,即便內存不足,GC進行垃圾收集的時候也不會主對象
動回收。blog
Object obj = new Object();隊列
軟引用:在內存不足的時候,GC進行垃圾收集的時候會被GC回收。內存
Object obj = new Object(); SoftReference<Object> softReference = new SoftReference<>(obj);get
弱引用:不管內存是否充足,GC進行垃圾收集的時候都會回收。虛擬機
Object obj = new Object(); WeakReference<Object> weakReference = new WeakReference<>(obj);效率
虛引用:和弱引用相似,主要區別在於虛引用必須和引用隊列一塊兒使用。
Object obj = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = new PhantomReference<>(obj, referenceQueue);
引用隊列:若是軟引用和弱引用被GC回收,JVM就會把這個引用加到引用隊列裏,若是是虛引用,在回收前就會被加到引用隊列裏。
引用計數法:給每一個對象添加引用計數器,每一個地方引用它,計數器就+1,失效時-1。若是兩個對象互相引用時,就致使沒法回收。
可達性分析算法:以根集對象爲起始點進行搜索,若是對象不可達的話就是垃圾對象。根集(Java棧中引用的對象、方法區中常量池中引用的對象、本地方法中引用的對象等。JVM在垃圾回收的時候,會檢查堆中全部對象是否被這些根集對象引用,不可以被引用的對象就會被垃圾回收器回收。)
常見的垃圾回收算法有:
標記-清除
標記:首先標記全部須要回收的對象,在標記完成以後統計回收全部被標記的對象,它的標記過程即爲上面的可達性分析算法。
清除:清除全部被標記的對象
缺點:
效率不足,標記和清除效率都不高
空間問題,標記清除以後會產生大量不連續的內存碎片,致使大對象分配沒法找到足夠的空間,提早進行垃圾回收。
複製回收算法
將可用的內存按容量劃分爲大小相等的2塊,每次只用一塊,當這一塊的內存用完了,就將存活的對象複製到另一塊上面,而後把已使用過的內存空間一次清理掉。
缺點:
將內存縮小了本來的通常,代價比較高
大部分對象是「朝生夕滅」的,因此沒必要按照1:1的比例劃分。
如今商業虛擬機採用這種算法回收新生代,但不是按1:1的比例,而是將內存區域劃分爲eden 空間、from 空間、to 空間 3 個部分。
其中 from 空間和 to 空間能夠視爲用於複製的兩塊大小相同、地位相等,且可進行角色互換的空間塊。from 和 to 空間也稱爲 survivor 空間,即倖存者空間,用於存放未被回收的對象。
在垃圾回收時,eden 空間中的存活對象會被複制到未使用的 survivor 空間中 (假設是 to),正在使用的 survivor 空間 (假設是 from) 中的年輕對象也會被複制到 to 空間中 (大對象,或者老年對象會直接進入老年帶,若是 to 空間已滿,則對象也會直接進入老年代)。此時,eden 空間和 from 空間中的剩餘對象就是垃圾對象,能夠直接清空,to 空間則存放這次回收後的存活對象。這種改進的複製算法既保證了空間的連續性,又避免了大量的內存空間浪費。
標記-整理
在老年代的對象大都是存活對象,複製算法在對象存活率教高的時候,效率就會變得比較低。根據老年代的特色,有人提出了「標記-壓縮算法(Mark-Compact)」
標記過程與標記-清除的標記同樣,但後續不是對可回收對象進行清理,而是讓全部的對象都向一端移動,而後直接清理掉端邊界之外的內存。
這種方法既避免了碎片的產生,又不須要兩塊相同的內存空間,所以,其性價比比較高。
分帶收集算法
根據對象存活的週期不一樣將內存劃分爲幾塊,通常是把Java堆分爲老年代和新生代,這樣根據各個年代的特色採用適當的收集算法。
新生代每次收集都有大量對象死去,只有少許存活,那就選用複製算法,複製的對象數較少就可完成收集。
老年代對象存活率高,使用標記-壓縮算法,以提升垃圾回收效率。
點擊下方連接免費獲取Android進階資料: