成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

談一談JVM垃圾回收

stormzhang / 3746人閱讀

摘要:這個算法看似不錯而且簡單,不過存在這一個致命傷當(dāng)兩個對象互相引用的時候,就永遠不會被回收于是引用計數(shù)算法就永遠回收不了這兩個對象,下面介紹另一種算法。

前言

? 如果要問Java與其他編程語言最大的不同是什么,我第一個想到的一定就是Java所運行的JVM所自帶的自動垃圾回收機制,以下是我學(xué)習(xí)JVM垃圾回收機制整理的筆記,希望能對讀者有一些幫助。

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

? 如何判斷對象已死?有兩種算法

引用計數(shù)算法

? 給對象添加一個計數(shù)器,每當(dāng)有一個地方引用它時,計數(shù)器的值就加一,當(dāng)引用失效的時候,計數(shù)器就減一 ,任何時刻計數(shù)器為0的對象就是不可能再被使用的時候。

? 這個算法看似不錯而且簡單,不過存在這一個致命傷(當(dāng)兩個對象互相引用的時候,就永遠不會被回收)

public class Obj{
  public Object instance=null;
}

Obj a=new Obj();
Obj b=new Obj();

a.instance=b;
b.instance=a;

a=null;
b=null;

于是引用計數(shù)算法就永遠回收不了這兩個對象,下面介紹另一種算法。

可達性分析算法

? 通過一系列被稱為“GC Roots”的對象作為起始點,從這些接點向下搜索,搜索所走過的路徑稱為引用鏈,當(dāng)一個對象與任何一個引用鏈沒有關(guān)聯(lián)的時候則可以被回收。

Java中,可作為GC Roots的對象包括下面集中

虛擬機棧(棧幀中的本地變量表)中引用的對象

方法區(qū)中類靜態(tài)屬性引用的對象

方法區(qū)中常量引用的對象

本地方法棧中JNI(Native方法)引用的對象

淺談引用

? 無論是計數(shù)器算法還是可達性分析算法,都與“引用”有關(guān),下面是Java中4種引用,強度依次減弱

強引用

? 強引用就是我們平時最熟悉的

Object obj=new Object();

? 只要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象。

軟引用

? 發(fā)生gc的時候,如果JVM內(nèi)存充足則不回收,用SoftReference類來實現(xiàn)軟引用。展示一個例子

        SoftReference softReference=new SoftReference<>(new Object());
        System.out.println("before gc  "+softReference.get());
        System.gc();
        System.out.println("after gc   "+softReference.get());

? 以下是輸出

before gc  java.lang.Object@2752f6e2
after gc   java.lang.Object@2752f6e2

可以看到軟引用的對象依然還在。

弱引用

? 一旦發(fā)生gc,無論JVM內(nèi)存充足與否,都會回收掉,用WeakReference類來實現(xiàn)弱引用。展示一個例子

        WeakReference softReference=new WeakReference<>(new Object());
        System.out.println("before gc  "+softReference.get());
        System.gc();
        System.out.println("after gc   "+softReference.get());

? 以下是輸出

before gc  java.lang.Object@2752f6e2
after gc   null

弱引用的對象已經(jīng)被回收!

虛引用

? 虛引用也稱為幽靈引用或者幻影引用,是最弱的一種引用,無法通過虛引用來取得一個對象實例,擁有虛引用的對象可以在任何時候被垃圾回收器回收。唯一的目的就是能在當(dāng)這個對象被回收的時候收到一個系統(tǒng)通知,可用PhantomReference類實現(xiàn)虛引用。

回收方法區(qū)

? 垃圾回收大多發(fā)生在Heap(堆區(qū)),因為在方法區(qū)進行垃圾回收效率較低,要判定一個類是否是“無用的類”條件比較苛刻,類需要同時滿足下面3個條件才能算是無用的類

該類所有實例已經(jīng)被回收,堆中不存在該類任何實例

加載該類的ClassLoader已經(jīng)被回收

該類對應(yīng)的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

什么時候回收?when?

? 首先,GC又分為minor GC 和 Full Gc(也稱為Major GC)。Java 堆內(nèi)存分為新生代和老年代,新生代中又分為1個Eden區(qū)域 和兩個 Survivor區(qū)域。

那么對于 Minor GC 的觸發(fā)條件:大多數(shù)情況下,直接在 Eden 區(qū)中進行分配。如果 Eden區(qū)域沒有足夠的空間,那么就會發(fā)起一次 Minor GC;對于 Full GC(Major GC)的觸發(fā)條件:也是如果老年代沒有足夠空間的話,那么就會進行一次 Full GC。

注意:上面所說的只是一般情況,實際上,需要考慮一個空間分配擔(dān)保的問題:

在發(fā)生Minor GC之前,虛擬機會先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象的總空間。如果大于則進行Minor GC,如果小于則看HandlePromotionFailure設(shè)置是否允許擔(dān)保失?。ú辉试S則直接Full GC)。如果允許,那么會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小,如果大于則嘗試Minor GC(如果嘗試失敗也會觸發(fā)Full GC),如果小于則進行Full GC。

System.gc()就是指的Full GC

但是,具體程序執(zhí)行到什么位置才會自動gc,這兒提兩個概念Safepoint和SafeRegion。

安全點(Safepoint)

? 安全點的選定是以程序“是否具有讓程序長時間執(zhí)行的特征”為標(biāo)準(zhǔn)選定的,“長時間執(zhí)行”最明顯的特征就是

指令序列復(fù)用

循環(huán)跳轉(zhuǎn)

異常跳轉(zhuǎn)等

對于Safepoint如何在GC發(fā)生時讓所有線程都跑到最近的安全點上停下來,有兩種方案搶先式中斷主動式中斷

搶先式中斷:不需要線程執(zhí)行的代碼主動配合,GC發(fā)生時,首先把所有線程全部中斷,如果發(fā)現(xiàn)有線程中斷的地方不在安全點上,就恢復(fù)線程,讓它“跑到”安全點上。(這種方案幾乎很少使用)

主動式中斷 :當(dāng)GC需要中斷線程的時候,不直接對線程操作,僅僅簡單設(shè)置一個標(biāo)志,各個線程執(zhí)行時主動去輪詢這個標(biāo)志,發(fā)現(xiàn)為true就自動掛起,輪詢的地方和安全點是重合的。

安全區(qū)域(Saferegion)

? 當(dāng)線程處于Sleep狀態(tài)或者Blocked狀態(tài),這時候線程無法響應(yīng)JVM的中斷請求,“走”到安全的地方去中斷掛起,JVM也顯然不太可能等待線程重新被分配CPU時間,這時候就需要安全區(qū)域來解決。

? 當(dāng)線程執(zhí)行到Safe Region中的代碼時,首先標(biāo)識自己已經(jīng)進入了Safe Region,當(dāng)JVM在發(fā)起GC時,就不用管標(biāo)識自己為Safe Region狀態(tài)的線程了。在線程要離開Safe Region時,他要檢查系統(tǒng)是否完成了整個GC過程,如果完成了,線程就繼續(xù)執(zhí)行,否則必須等待直到收到可以安全離開Safe Region的信號為止。

如何回收?how? 標(biāo)記-清除 算法

? 算法分為標(biāo)記清除兩個階段,首先標(biāo)記出所有需要回收的對象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對象。他的不足主要有兩個:

效率問題:標(biāo)記和清除兩個過程的效率都不高

空間問題:標(biāo)記清除之后,會產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會導(dǎo)致之后分配大對象時,無法找到足夠的連續(xù)內(nèi)存而提前觸發(fā)GC

復(fù)制算法

? 復(fù)制算法可以將容量劃分為大小相等的兩塊,每次只使用其中的一塊,當(dāng)一塊內(nèi)存被用完了就將還存活的對象一次復(fù)制到另一塊內(nèi)存上,然后把已經(jīng)使用過的內(nèi)存一次清理掉。不過因此內(nèi)存縮小為原來的一半,代價過高。

? 現(xiàn)在的商業(yè)虛擬機普遍采用這種算法來回收新生代,將新生代分為較大的一塊Eden空間和兩塊較小的Survivor空間,HotSpot默認其比例為8:1:1,使用時,每次使用Eden加上其中一塊Survivor,回收時,將Eden和Survivor中還存活的對象一次性復(fù)制到另一塊Survivor中,最后清理掉Eden和剛才用過的Survivor區(qū)。

標(biāo)記-整理 算法

? 標(biāo)記過程與“標(biāo)記-清除”算法一樣,然后讓所有存活的對象都向同一端移動,然后直接清理端邊界以外的內(nèi)存。

分代收集算法

? 將Java堆分為新生代和老年代,在新生代中每次垃圾回收都有大批對象死去,少量存活,可以使用復(fù)制算法,而老年代中對象存活率高沒有額外的空間對它進行分配擔(dān)保,必須使用“標(biāo)記-整理”或者“標(biāo)記-清理”算法來回收。

談?wù)凣1垃圾收集器

? 在最近更新的JDK9中,JVM默認的垃圾收集器切換成了G1,那么G1有什么特點呢?總結(jié)以下最大的四個特點

并行與并發(fā):G1能充分利用多CPU、多核環(huán)境下的硬件優(yōu)勢,使用多個CPU,(CPU或者CPU核心)來縮短Stop-The-World停頓的時間,部分其他收集器需要停頓Java線程執(zhí)行的GC動作,G1可以通過并發(fā)的方式讓Java繼續(xù)執(zhí)行。

分代收集:G1不需要其他收集器配合就能獨立管理整個GC堆,G1采用不同的方式去處理新創(chuàng)建的對象、已經(jīng)存活一段時間的對象熬過多次GC的舊對象以獲取更好的收集效果。

空間整合:G1從整體來看是基于“標(biāo)記-整理”算法,局部上來看是基于復(fù)制算法,這兩種算法都不會產(chǎn)生內(nèi)存碎片,有利于程序長時間運行。

可預(yù)測的停頓:G1除了追求低停頓外,還能建立可預(yù)測的停頓時間模型,能讓使用者明確指定在一個長度為M毫秒的時間片段內(nèi),消耗在垃圾收集上的時間不超過N毫秒。

資料來源
《深入理解Java虛擬機》P61-P84

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://hztianpu.com/yun/69424.html

相關(guān)文章

  • js技術(shù) - 收藏集 - 掘金

    摘要:還記得剛開始學(xué)習(xí)的時候,內(nèi)存管理前端掘金作為一門高級語言,并不像低級語言那樣擁有對內(nèi)存的完全掌控。第三方庫的行代碼內(nèi)實現(xiàn)一個前端掘金前言本文會教你如何在行代碼內(nèi),不依賴任何第三方的庫,用純實現(xiàn)一個。 (譯) 如何使用 JavaScript 構(gòu)建響應(yīng)式引擎 —— Part 1:可觀察的對象 - 掘金原文地址:How to build a reactive engine in JavaSc...

    Guakin_Huang 評論0 收藏0
  • js技術(shù) - 收藏集 - 掘金

    摘要:還記得剛開始學(xué)習(xí)的時候,內(nèi)存管理前端掘金作為一門高級語言,并不像低級語言那樣擁有對內(nèi)存的完全掌控。第三方庫的行代碼內(nèi)實現(xiàn)一個前端掘金前言本文會教你如何在行代碼內(nèi),不依賴任何第三方的庫,用純實現(xiàn)一個。 (譯) 如何使用 JavaScript 構(gòu)建響應(yīng)式引擎 —— Part 1:可觀察的對象 - 掘金原文地址:How to build a reactive engine in JavaSc...

    zhou_you 評論0 收藏0
  • Java開發(fā) 大廠面試整理

    摘要:用戶態(tài)不能干擾內(nèi)核態(tài)所以指令就有兩種特權(quán)指令和非特權(quán)指令不同的狀態(tài)對應(yīng)不同的指令。非特權(quán)指令所有程序均可直接使用。用戶態(tài)常態(tài)目態(tài)執(zhí)行非特權(quán)指令。 這是我今年從三月份開始,主要的大廠面試經(jīng)過,有些企業(yè)面試的還沒來得及整理,可能有些沒有帶答案就發(fā)出來了,還請各位先思考如果是你怎么回答面試官?這篇文章會持續(xù)更新,請各位持續(xù)關(guān)注,希望對你有所幫助! 面試清單 平安產(chǎn)險 飛豬 上汽大通 浩鯨科...

    Scorpion 評論0 收藏0
  • JavaScript運行原理解析

    摘要:執(zhí)行過程引擎會加載源代碼,把它分解成字符串又叫做分詞,再把這些字符串轉(zhuǎn)換成編譯器可以理解的字節(jié)碼,然后執(zhí)行這些字節(jié)碼。接著四個進程開始參與進來,分析和執(zhí)行解析器所生成的字節(jié)碼。 JavaScript運行原理 知其然,也要知其所以然,這里主要談一談對JavaScript運行原理的理解。 JAVA虛擬機 首先我們從JAVA虛擬機說起。 首先說一下為什么要做成虛擬機,因為機器不同,如果沒有虛...

    goji 評論0 收藏0
  • Java問題匯總,持續(xù)更新到GitHub

    摘要:目錄介紹問題匯總具體問題好消息博客筆記大匯總年月到至今,包括基礎(chǔ)及深入知識點,技術(shù)博客,學(xué)習(xí)筆記等等,還包括平時開發(fā)中遇到的匯總,當(dāng)然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續(xù)完善開源的文件是格式的同時也開源了生活博客,從年 目錄介紹 00.Java問題匯總 01.具體問題 好消息 博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識點,Android技...

    beita 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<