垃圾收集器以及內(nèi)存分配策略

哪些內(nèi)存需要回收

當(dāng)垃圾收集器對(duì)堆進(jìn)行回收前, 首先要確定當(dāng)前對(duì)象是否需要被回收, 所以第一步, 死亡判定
, 何為死亡呢, 就是說(shuō)當(dāng)前這個(gè)對(duì)象沒(méi)有被其他地方引用他, 他用不到了,沒(méi)作用了, 就判定死亡。
死亡判定的兩種算法,
引用計(jì)數(shù)器, 記錄該對(duì)象被引用的次數(shù), 實(shí)現(xiàn)簡(jiǎn)單, 缺點(diǎn)明顯, 無(wú)法解決循環(huán)引用的問(wèn)題。
可達(dá)性算法, 該算法也是主流JVM所使用的, 我們會(huì)生成一系列的GC Roots, 像這個(gè)樣子

可達(dá)性

判斷對(duì)象是否存活就是尋找引用鏈, 是否可達(dá)GC Roots,那么就要問(wèn)了, GC Roots是什么呢
GC Roots 也是堆中我們生成的對(duì)象, 只是這個(gè)對(duì)象有被下面幾個(gè)地方引用到, 那么就可作為GC Roots

  1. 虛擬機(jī)棧的棧幀中, 即方法中所引用的對(duì)象, 這點(diǎn)好理解吧, 我們?cè)谑褂靡粋€(gè)方法的時(shí)候, 可能會(huì)new幾個(gè)對(duì)象出來(lái), 那么這些對(duì)象都可以認(rèn)為是GC Roots, 這里的GC Roots 會(huì)隨著方法出棧而退出GC Root 集合, 就有被回收的機(jī)會(huì)了。
  2. 方法區(qū)中常量引用的對(duì)象, 方法區(qū),你又可以理解為永久代, 那么這里又是常量所引用的, 地址不會(huì)發(fā)生變化, 那么自然可以被當(dāng)做GC Roots了, 個(gè)人認(rèn)為這個(gè)GC Roots可以一直活著。
  3. 本地方法棧引用的對(duì)象, 和一同理

在jdk1.2,對(duì)引用的那根線, 也有了定義

對(duì)于引用呢, 我們有4種引用方式

  • 強(qiáng)引用, new 的方式, 都是強(qiáng)引用, 垃圾收集器永遠(yuǎn)不會(huì)回收被引用的對(duì)象
  • 軟引用 內(nèi)存即將發(fā)生溢出異常的時(shí)候, 會(huì)去先把這些引用回收掉, 看看還會(huì)不會(huì)溢出
  • 弱引用, 垃圾收集器工作時(shí), 每次垃圾回收的時(shí)候,都會(huì)回收掉這個(gè)對(duì)象
  • 虛引用, 弱的不行, 能干啥我也不知道
    關(guān)于四個(gè)引用使用場(chǎng)景, 后來(lái)會(huì)再說(shuō)的。
    那么除了對(duì)堆的回收, 方法區(qū)也是會(huì)有回收的, 主要針對(duì)廢棄常量和無(wú)用的類, 回收條件較苛刻, 還得調(diào)JVM參數(shù)
怎么回收這些對(duì)象

我們之前有點(diǎn)東西忘說(shuō)了, 就是在進(jìn)行可達(dá)性分析的時(shí)候, 會(huì)對(duì)要回收的對(duì)象進(jìn)行標(biāo)記, 標(biāo)記了的就要被回收, 針對(duì)回收方式, 由以下算法演進(jìn)

  1. 標(biāo)記-清除算法
    將需要回收的對(duì)象標(biāo)記, 然后直接清除
標(biāo)記清除算法

別看圖是很規(guī)整的, 堆中分配的空間是由對(duì)象決定的, 所以呢, 這樣的標(biāo)記清除, 則會(huì)讓內(nèi)存碎片化嚴(yán)重, 這時(shí)候創(chuàng)建對(duì)象呢, 就是向這些回收的后的空隙內(nèi)存中選取合適大小的塊來(lái)分配, 如果這個(gè)對(duì)象需要很大的內(nèi)存塊,而又沒(méi)有找到, 那么就尷尬了, 對(duì)吧。

  1. 復(fù)制算法
    將內(nèi)存分為兩塊, 每次回收, 將存活對(duì)象扔到另一邊, 清除用過(guò)的那塊

    復(fù)制算法

    就是兩塊內(nèi)存換著用, 來(lái)回倒, 另一塊直接清0, 當(dāng)然, 這樣做缺點(diǎn)也很明顯, 浪費(fèi)了一整半空間, 再講分代收集的時(shí)候, 我們會(huì)繼續(xù)談此算法。

  2. 標(biāo)記-整理
    很類似于標(biāo)記清除, 只是直接移動(dòng)存貨對(duì)象到一塊, 然后整體清零邊界, 像這個(gè)樣子

標(biāo)記整理
  1. 分代收集
    啊哈, 分代收集和我們之前的對(duì)象頭扯到一塊了, 我們知道對(duì)象頭里包含了對(duì)象的分代年齡, 對(duì)于不同的年齡呢, 我們把GC堆分為了新生代, 和老年代, 新生代回收都能回收走大量的對(duì)象, 老年代一般死亡的對(duì)象很少, 因此呢, 針對(duì)這樣的問(wèn)題, 新生代采用復(fù)制算法(優(yōu)化過(guò)的, 針對(duì)新生代需進(jìn)行大量回收),老年代采用標(biāo)記整理或標(biāo)記清楚。
    優(yōu)化的復(fù)制算法長(zhǎng)啥樣呢, 我們先來(lái)描述一下, 將原本的一半一半, 變成了8-1-1, 我們清楚, 新生代伴隨大量?jī)?nèi)存回收, 存活下來(lái)的比較少, 每次使用8-1 塊, 然后, 回收的時(shí)候, 將存活的復(fù)制到另一塊小區(qū)域中, 并且清除8-1塊, 就不畫圖了。這里要注意, 有時(shí)候可能存活的不止1的比例, 超出1的呢, 會(huì)通過(guò)分配擔(dān)保機(jī)制, 提前進(jìn)入老年代。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容