java的垃圾回收#垃圾回收算法

java之所以能夠?qū)崿F(xiàn)自動(dòng)內(nèi)存分配,是因?yàn)閖vm幫我們完成了兩件事

  • 幫助對(duì)象分配內(nèi)存
  • 幫助回收分配給對(duì)象的內(nèi)存

回收哪些地方的內(nèi)存

jvm內(nèi)存分類可見下圖
線程私有的內(nèi)存占用在程序編譯期就是可知的,堆和方法區(qū)的內(nèi)存是在程序運(yùn)行期才能確定,GC負(fù)責(zé)處理的就是線程共享的內(nèi)存: 方法區(qū)

Paste_Image.png

對(duì)象已死么

應(yīng)該回收哪些對(duì)象占用的內(nèi)存呢,需要找出“死掉”的對(duì)象,兩種方法可以找到

  • 引用計(jì)數(shù)法
    由于引用計(jì)數(shù)法容易造成兩個(gè)對(duì)象相互循環(huán)引用問題,主流jvm并不采用該方法
  • 可達(dá)性分析 主流jvm采用的方法
    如下圖,那些無法到達(dá)GC Roots的對(duì)象,就是可以被回收的對(duì)象
Paste_Image.png

GCRoots中的對(duì)象包括

  1. 虛擬機(jī)棧中(局部變量表)引用的對(duì)象
  2. 方法區(qū)中類的靜態(tài)屬性引用的對(duì)象
  3. 方法區(qū)中常量引用的對(duì)象
  4. JNI中引用的對(duì)象

那些發(fā)現(xiàn)不能到達(dá)GC Roots的對(duì)象并不會(huì)立即回收,在真正回收之前,對(duì)象至少要被標(biāo)記兩次。當(dāng)?shù)谝淮伪话l(fā)現(xiàn)不可達(dá)時(shí),該對(duì)象會(huì)被標(biāo)記一次,同時(shí)調(diào)用此對(duì)象的finalize()方法(如果有);在第二次被發(fā)現(xiàn)不可達(dá)后,對(duì)象被回收。
利用finalisze()方法,對(duì)象可以逃離一次被回收的命運(yùn),但是只有一次。逃命方法如下,需要在finalize()方法中給自己加一個(gè)GCRoots中的hook

<pre>
public class EscapeFromGC(){
public static EscapeFromGC hook;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize mehtod executed!");
EscapeFromGC.hook = this;
}
</pre>

垃圾回收算法

  1. 標(biāo)記清除(Mark Sweep)算法


    Paste_Image.png

    顧名思義,此方法有兩個(gè)階段,標(biāo)記需要清除的對(duì)象,然后清除。
    有兩個(gè)問題

    • 效率低
    • 會(huì)產(chǎn)生很多不連續(xù)內(nèi)存,分配大對(duì)象時(shí),容易提前引起另一次垃圾回收
  2. 復(fù)制算法(Copying)
    考慮將內(nèi)存分成兩個(gè)一樣大的區(qū)域,一邊的內(nèi)存用完了,就把所用存活的對(duì)象放到另一邊內(nèi)存

    • 效率高,每次針對(duì)某一片內(nèi)存進(jìn)行內(nèi)存回收,不用考慮內(nèi)存碎片化
    • 有一定空間浪費(fèi)


      Paste_Image.png

      實(shí)際上,98%的新時(shí)代對(duì)象都是很快要被回收的,所以實(shí)際jvm并不會(huì)按照1:1來分配內(nèi)存。而是將內(nèi)存分為一塊較大的Eden區(qū)和兩塊較小的Survival區(qū),默認(rèn)比例為8:1:1,這樣實(shí)際上新時(shí)代的可用內(nèi)存為實(shí)際內(nèi)存的90%。

  3. 標(biāo)記整理(Mark Compact)算法


    Paste_Image.png

    根據(jù)老年代的特點(diǎn)(大部分對(duì)象的存活周期長(zhǎng),需要盡可能利用內(nèi)存)
    第一步和標(biāo)記清除算法的標(biāo)記一樣,但是第二步不是清除,而是讓內(nèi)存一次往前移動(dòng),占滿空閑內(nèi)存。

  4. 分代(Generational )收集
    現(xiàn)代商業(yè)系統(tǒng)采用分帶收集算法,根據(jù)對(duì)象的生存周期把內(nèi)存分為新生代和老生代。

  • 新生代采用復(fù)制算法
  • 老生代采用標(biāo)記整理算法

垃圾收集器

垃圾收集器的發(fā)展方向,就是朝著更高效率發(fā)展。具體在減少GC的時(shí)間
下圖是常用的垃圾收集器,連線表示在新生代和老生代可以一起配合工作的組合

Paste_Image.png

內(nèi)存分配的幾個(gè)原則

  1. 對(duì)象優(yōu)先在Eden區(qū)域分配
  2. 大對(duì)象直接進(jìn)入老年代
  3. 長(zhǎng)期存活對(duì)象進(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

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