今天不是給你們介紹對象的,給你們介紹下垃圾,由於垃圾會霸佔內存,需清理之,今天咱們聊聊JVM用什麼方式回收垃圾的!先上圖吧,咱們看看對象的生命週期。算法
先解釋幾個名詞:微信
新生的對象都在eden區,當eden區滿時容納不了大的對象,會觸發GC,若是對象還活着,小對象進入From區或者是to區,這兩塊區域有一塊是空的,假設如今裝對象是from區,那麼,當GC後from區全部對象會複製到to區,而且清空from區域,存活對象年紀會增大一歲,當對象到達必定年紀以後,就會進入老年代了。若是對象比較大,Surviror裝不下,會直接進入老年代,若是老年代也裝不下,會報錯:堆內存溢出。ide
簡單介紹垃圾生命週期後,咱們看看垃圾清理算法。優化
引用計數法怎麼判斷一個對象是垃圾?就看是否有引用指向該對象。引用計數法表示若是一個對象有1個引用計數器就是1,2個引用計算器是2,若是沒有引用,計數器爲0,也就是垃圾對象。缺點是對象相互引用,對象沒法回收。畫圖舉個簡單案例。spa
如上圖代碼:teacher持自身引用同時持有student的引用,計數器爲2,student持自身引用同時持有teacher的引用,計數器爲2,這叫相互引用,最終致使teacher或者student對象都沒法被回收。因此如今垃圾回收器通常不採用引用計數法。線程
標記-清除分兩步,GC線程先標記可達對象,當發生GC時,清除不可達對象。缺點是回收後內存碎片。對象
如上圖,咱們知道分配內存都是連續的,垃圾對象回收後,內存很不規則,不利於內存使用效率。垃圾對象是不可達的?那什麼叫可達對象呢,什麼叫不可達對象呢?blog
理論性的東西仍是比較難理解,咱們畫圖表示下。生命週期
假設:new Object()對應的堆地址是0xJL。內存
Object object = new Object(); 棧object引用指向new Object()對應的0xJL地址,new Object()對象可達,其中object就叫作根對象。
object = null; 告訴gc線程,沒有引用指向0xJL了,那這塊內存就有可能被標記爲垃圾對象。
複製算法須要將一塊空白的內存一分爲二,GC後,將可達對象所有移動到另外一塊內存。新生代對象朝生夕死,GC後將活着的對象移動到另外一塊空內存,並將當前使用的內存清空。每次GC,循環往復。
如上圖:新生代採用複製算法,GC回收前使用from區域,GC後使用to內存區域。
標記整理算法基於標記清除算法作了必定優化,gc線程首先從根節點開始標記可達對象,並將可達對象壓縮到內存頂部,最後清除邊界區域,老年代對象生命週期長,比較適用於標記整理算法。
如上圖:當老年代滿了,會觸發Full GC,將內存壓縮整理。
畫圖解釋了幾種GC算法的含義和缺點,但願對你有幫助,喜歡的請點贊加關注哦。點關注,不迷路,我是【叫練】公衆號,微信號【jiaolian123abc】邊叫邊練。