一、引用計數法:給對象添加一個引用計數器,當有一個地方引用它時,計數器+1;當引用失效時,計數器-1。
任何狀況下,計數器爲0的對象,都是不可以使用的。算法
優勢:簡單,高效spa
缺點:循環引用對象
二、可達性分析算法:經過一系列的名爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈(Reference Chain),當一個對象到 GC Roots 沒有任何引用鏈相連(用圖論的話來講就是從 GC Roots 到這個對象不可達)時,則證實此對象是不可用的。內存
特色:GC Roots→引用鏈虛擬機
三、引用:分爲 強引用,軟引用,弱引用,虛引用。效率
強引用:引用在,不回收搜索
軟引用:SoftReference OOM前,把這些對象回收 若是仍OOM→拋出異常循環
弱引用:WeakReference 下一次GC則清除引用
虛引用: PhantomReference 回收時→系統通知程序
一、標記-清除:
標記全部要回收的對象 統一回收
缺點:效率問題 標記和清除的效率都不高 空間問題 大量不連續的內存碎片
二、複製
將可用內存的容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊用完了,就將還存活的對象複製到另一塊上面,而後再把已使用過的內存空間一次清理掉。
缺點: 內存→1/2
優勢:實現簡單 運行高效
新生代: 1 Eden 2 Survivor
三、標記-整理:
標記過程仍然與「標記-清除」算法同樣,但不是直接對可回收對象進行清理,而是讓全部存活的對象向一端移動,而後直接清理掉邊界之外的內存。
老年代 存活率高
四、分代收集
why 不一樣對象,存活週期不一樣 選擇最適合的算法
新生代 大批對象死去、少許存活 複製
老年代 對象存活率高 標記-整理
一、新生代:主要存放的是哪些很快就會被GC回收掉的或者不是特別大的對象(這個大就要看你是否設置了-XX:PretenureSizeThreshold 參數了)。新生代採用的複製算法,即將新生代分爲3個區:較大的Eden和兩個較小的Survivor(默認的Eden:Survivor = 8:1)。發生在新生代的GC爲Minor GC 。在Minor GC時會將新生代中還存活着的對象複製進一個Survivor中,而後對Eden和另外一個Survivor進行清理。因此,日常可用的新生代大小爲Eden的大小+一個Survivor的大小。
二、老年代:老年代則是存放那些在程序中經歷了好幾回回收仍然還活着或者特別大的對象(這個大就要看你是否設置了-XX:PretenureSizeThreshold 參數了)。老年代採用的是標記-清除或者標記-整理算法,這兩個算法主要看虛擬機採用的哪一個收集器,兩種算法的區別是:標記-清除可能會產生大量連續的內存碎片。在老年代中的GC則爲Major GC。Major GC和Full GC會形成stop-the-world。
三、那麼什麼狀況下,新生代的對象會進入老年代呢?
首先就是分配擔保機制:當Minor GC時,新生代存活的對象大於Survivor的大小時,這時一個Survivor裝不下它們,那麼它們就會進入老年代。
還有其餘的狀況:若是設置了-XX:PretenureSizeThreshold3M 那麼大於3M的對象就會直接就進入老年代。
還有,在新生代的每一次Minor GC 都會給在新生代中的對象+1歲,默認到15歲時就會重新生代進入老年代,能夠經過-XX:MaxTenuringThreshold來設置這個臨界點。
相比較而言,在老年代中的對象比新生代中的對象不易回收許多。