垃圾收集(Garbage collection, GC)android
收集原理:算法
1、引用計數算法:給對象中添加一個引用計數器,每當有一個地方引用它,計數器就加一;引用實效,就減一;它的問題是沒法解決循環引用。
二、可達性分析算法:以一系列被稱爲‘GC Roots’的對象爲起點,像下搜索,能到達的對象爲可用,不然爲不可用。
GC Roots對象包括:
虛擬機棧(棧幀中的本地變量表)中引用的對象
方法區中類靜態屬性引用的對象。
方法區中常量引用的對象
本地方法棧中JNI(即通常說的Native方法)引用的對象。
finalize方法安全
1、若是一個對象沒有覆蓋finalize方法,當對象被回收打時候,不會執行;
二、若是有覆蓋,可是這個對象以前已經執行過一次這個方法,當對象被回收的時候,也不會執行;
三、GC時,回收掉一個對象,若是它有覆蓋finalize方法,而且以前沒有被調用過,並不立刻銷燬它,而是將它移到F-Quene隊列,並又虛擬機啓動一個優先級低的Finalizer線程執行它,可是並不保證
等待它結束。
GC算法:多線程
1、標記-清除算法(Mark Sweep):
先標記不可達隊對象,而後統一清除;
不足是會產生內存碎片;並且效率也不高
二、複製算法:
將內存2等分,當一份快用完時,將可達對對象複製到另外一份,而後清空當前對象。
優勢是效率高,肯定是內存利用率低。
三、標記整理算法:
先標記可達的、不可達的對象,而後將可達的內存前移,最後直接清理掉後面的對象。
四、分代收集算法:
將內存劃分爲幾塊,而後根據每塊的特色選擇不一樣的算法。例如:新生代、老年代;
安全點、安全區域:併發
目前全部的GC回收時,都須要暫停用戶線程,可是用戶線程並非在每個地方都可以被GC線程暫停。目前採用的策略是,GC發出一箇中斷型號,用戶線程每在到達安全點點時候,去讀這個狀態,決定是否
暫停。
上述策略解決不了,在中斷信號發出以前用戶線程已經進入了掛起或者等待狀態(此時不在安全點);因此提出安全區點概念;
安全區:
指一段區域的代碼段,引用不會發生變化。
線程在進入安全區點時候,會標記本身已經進入了安全區,此時若是發起GC,能夠不用理會。若是線程離開安全區時,GC已經完成GC Roots對象的枚舉,哪線程繼續執行,不然需等待枚舉完成。
收集器:spa
1、初生代收集器:
Serial:單線程的,而且會STOP THE WORLD,STW,即在GC到時候會中止其餘用戶線程;採用複製算法
ParNew:多線程的,線程數和CPU數相同,其餘和Serial類似;
Parallel Scavenge:與ParNew 類似,其目標是達到可控的吞吐量(Throughput),吞吐量就是CPU用於用戶線程的時間/CPU的總多時間;可是它不關注停頓時間。
二、老年代收集器:
Serial Old:Serial 的老年版;一樣是採用單線程收集器;採用標記-整理算法;另一個用途是做爲CMS收集器的備案;
Parallel Old:Parallel Scavenge的老年班;
CMS(Concurrent Mark Sweep):使用標記-清除算法;以最短回收停頓時間爲目標的收集器;將回收分爲4各步驟:
a、初始標記:須要STW用戶線程
b、併發標記:能夠和用戶線程併發執行,好比有4各用戶線程,4個CPU這個時候GC線程也會和用戶線程輪流使用CPU。沒有阻塞,即爲併發。並行指同時運行。
c、從新標記:須要STW
d、併發清除:能夠併發
G1收集器:目前在低停頓時間上已經能夠和CMS媲美,在低吞吐量上面沒有表現的更加優秀。
總結:目前主流的虛擬機都是使用分代回收的機制;一、新生代和老年代可採用不一樣的收集器,互相配合完成回收任務,虛擬機可使用參數配置具體採用那種垃圾回收組合二、將堆分爲新生代和老年代,新生代又分爲一個Eden區,2個Survivor區,其中一般Eden / Survivor = 8, 也可使用參數配置。三、一般新生代使用一個Eden、一個Survivor,回收時,將可達對象copy到另一個Survivor;若是不夠,就移動到老年代,若是再不夠就啓動Full GC,仍是不夠就OOM四、大對象(新生代放不了,或者超過了設置的值)或者長期(4bit,默認15次GC,或者自定義的)存活對象被移入年老代;五、android 採用的多是CMS策略變種。