最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM垃圾回收機(jī)制和垃圾回收器詳細(xì)解說

 更新時(shí)間:2022年07月18日 16:08:05   作者:lose_rose777  
這篇文章主要介紹了JVM垃圾回收機(jī)制和垃圾回收器,為了讓程序員更加專注于代碼的實(shí)現(xiàn),而不用過多的考慮內(nèi)存釋放的問題,所以在Java語言中,有了自動的垃圾回收機(jī)制,也是我們常常提及的GC,需要的朋友可以參考下

什么是垃圾回收機(jī)制

為了讓程序員更加專注于代碼的實(shí)現(xiàn),而不用過多的考慮內(nèi)存釋放的問題,所以在Java語言中,有了自動的垃圾回收機(jī)制,也是我們常常提及的GC(Garbage Collection)

有了這個(gè)垃圾回收機(jī)制之后,程序員只需要考慮內(nèi)存的申請即可,內(nèi)存的釋放由系統(tǒng)自動識別完成。在垃圾回收的時(shí)候,不同的對象引用類型,GC會采用不同的回收時(shí)機(jī),換句話說自動垃圾回收算法就會變得非常重要,如果因?yàn)樗惴ǖ牟缓侠?,?dǎo)致內(nèi)存資源一直沒有釋放,同樣也可能導(dǎo)致內(nèi)存資源一直沒有被釋放,同樣也可能會導(dǎo)致內(nèi)存溢出

對象什么時(shí)候可以被垃圾回收

簡單用一句話來說:人如果一個(gè)或者多個(gè)對象沒有任何的引用指向它,那么這個(gè)對象現(xiàn)在就是垃圾,如果定位成垃圾,那么就有可能被垃圾回收器回收

如果要定位什么是垃圾,有兩種方式來確定,第一個(gè)是引用計(jì)數(shù)法,第二個(gè)是可達(dá)性分析算法

引用計(jì)數(shù)法

一個(gè)對象被引用一次,在當(dāng)前對象頭上遞增一次引用次數(shù) ,如果這個(gè)對象的引用次數(shù)為0,代表這個(gè)對象可以被回收

String demo = new String("123");

String demo = null;

當(dāng)對象間出現(xiàn)了循環(huán)引用的話,則引用計(jì)數(shù)法就會失效,如下圖:

雖然a和b都為null,但是由于a和b存在循環(huán)引用,這樣a和b永遠(yuǎn)都不會被回收

引用計(jì)數(shù)法的優(yōu)點(diǎn):

  • 實(shí)時(shí)性較高,無需等到內(nèi)存不夠的時(shí)候,才開始回收,運(yùn)行時(shí)根據(jù)對象的計(jì)數(shù)器是否為0,就可以直接回收
  • 在垃圾回收過程中,應(yīng)用無需掛起。如果申請內(nèi)存時(shí),內(nèi)存不足,則立刻報(bào)OOM錯(cuò)誤
  • 區(qū)域性,更新對象的計(jì)數(shù)器時(shí),只是影響到該對象,不會掃描全部對象

缺點(diǎn):

  • 每次對象被引用時(shí),都需要去更新計(jì)數(shù)器,有一點(diǎn)時(shí)間開銷
  • 浪費(fèi) CPU 資源,即使內(nèi)存夠用,仍然在運(yùn)行時(shí)進(jìn)行計(jì)數(shù)器的統(tǒng)計(jì)
  • 無法解決循環(huán)引用問題,會引發(fā)內(nèi)存泄露 (最大的缺點(diǎn))

可達(dá)性分析算法

現(xiàn)在的虛擬機(jī)采用的都是通過可達(dá)性分析算法來確定哪些內(nèi)容是垃圾

首先會存在一個(gè)根節(jié)點(diǎn)(GC Roots),引出它下面指向的下一個(gè)節(jié)點(diǎn),在以下一個(gè)節(jié)點(diǎn)開始為開始找到它下面的節(jié)點(diǎn),依次往下類推,直到所有節(jié)點(diǎn)全部遍歷完畢。這個(gè)思想類似于算法中的并查集

如上圖,X和Y就是GC Roots無法到達(dá)的節(jié)點(diǎn),那么X和Y就可以被認(rèn)為是垃圾

根對象是那些肯定不能當(dāng)作垃圾回收的對象,就可以當(dāng)作根對象。一般有四種類型可以選做根對象:

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

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

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

本地方法棧中JNI(即一般說的Native方法)引用的對象(不常用)

JVM垃圾回收算法有哪些

剛剛已經(jīng)講解完了如何定義垃圾,那么定義完成之后的垃圾有一系列的處理算法

標(biāo)記清除算法

標(biāo)記清除算法,是將垃圾回收分為兩個(gè)階段,分別是標(biāo)記和清除

  • 根據(jù)可達(dá)性分析算法得出了垃圾進(jìn)行標(biāo)記
  • 對這些標(biāo)記為可回收的內(nèi)容進(jìn)行垃圾回收

標(biāo)記清除算法有一定的劣勢:

  • 效率比較低,標(biāo)記和清除兩個(gè)動作都是需要遍歷所有的對象,并且GC的時(shí)候,需要停止應(yīng)用程序,對于交互性要求比較高的應(yīng)用而言這個(gè)不是很推薦
  • (重要)通過標(biāo)記清除算法清理出來的內(nèi)存,碎片化比較嚴(yán)重,因?yàn)楸换厥盏膶ο罂赡艽嬖谟趦?nèi)存的各個(gè)角落,所以清理出來的內(nèi)存不是很連貫

復(fù)制算法

復(fù)制算法的核心就是,將原來的內(nèi)存空間一分為二,每次都是用其中的一塊內(nèi)存。在垃圾回收的時(shí)候,將正在使用的對象復(fù)制到另一個(gè)內(nèi)存空間中,然后將該內(nèi)存空間清空,交換兩個(gè)內(nèi)存的角色,完成垃圾的

如果內(nèi)存中的垃圾對象較多,需要復(fù)制的對象就較少,這種情況下適合使用該 方式并且效率比較高,反之,則不適合

復(fù)制算法的執(zhí)行流程:

  • 將內(nèi)存區(qū)域分成兩個(gè)部分,每次只是操作其中的一個(gè)
  • 當(dāng)進(jìn)行垃圾回收的時(shí)候,將正在使用的內(nèi)存區(qū)域中的存活對象移動到未使用的內(nèi)存區(qū)域。當(dāng)移動完成之后,對這一部分內(nèi)存進(jìn)行一次性清除

優(yōu)點(diǎn):

  • 在垃圾對象多的情況下,效率較高
  • 清理后,內(nèi)存無碎片

缺點(diǎn):

  • 分配的2塊內(nèi)存空間,在同一個(gè)時(shí)刻,只能使用一半,內(nèi)存使用率較低

標(biāo)記整理算法

標(biāo)記整理算法是在標(biāo)記清除算法的基礎(chǔ)上,做了優(yōu)化和改進(jìn)的算法。和標(biāo)記清除算法一樣,也是從根節(jié)點(diǎn)開始,對對象的引用進(jìn)行標(biāo)記,在清理階段,并不是簡單的直接清理可回收對象,而是將存活對象都向內(nèi)存的另一端移動,讓然后清理邊界以外的垃圾,從而解決了碎片化的問題

標(biāo)記整理算法的執(zhí)行流程:

  • 標(biāo)記垃圾
  • 需要清楚的向右走,不需要清楚的向左走
  • 清除邊界以外的垃圾

優(yōu)缺點(diǎn):

  • 解決了標(biāo)記清除算法的碎片化的問題
  • 標(biāo)記壓縮算法多了一步,對象移動內(nèi)存位置的步驟,其效率也有有一定的影響
  • 復(fù)制算法標(biāo)記完就復(fù)制,但標(biāo)記整理算法得等把所有存活對象 都標(biāo)記完畢,再進(jìn)行整理

分代收集算法

在Java8時(shí),堆被分成兩份新生代和老年代(1:2),在Java7的時(shí)候,還存在一個(gè)永久代,Java8將其移動到本地內(nèi)存的元空間中

對于新生代,內(nèi)部被分為三個(gè)區(qū)域:Eden區(qū),兩個(gè)大小完全相同的survivor區(qū)S0(from)和S1(to)(8:1:1)

分代收集算法執(zhí)行流程:

新建的對象都會先分配代eden區(qū),當(dāng)eden區(qū)內(nèi)存不足的時(shí)候,會標(biāo)記eden區(qū)和from區(qū)(現(xiàn)階段還沒有)的存活對象

將存活下來的對象采用復(fù)制算法復(fù)制到to中,復(fù)制完畢之后,eden和from內(nèi)存得以釋放

經(jīng)過一段時(shí)間之后,eden區(qū)的內(nèi)存又不足了,標(biāo)記eden區(qū)和to區(qū)存活的對象,將存貨的對象復(fù)制到from區(qū)

當(dāng)幸存區(qū)對象熬過幾次回收(最多15次),晉升到老年代(幸存區(qū)內(nèi)存不足 或大對象會導(dǎo)致提前晉升)

MinorGC 、 Mixed GC 、 FullGC 的區(qū)別是什么

  • MinorGC【young GC】發(fā)生在新生代的垃圾回收,暫停時(shí)間短(STW:暫停所有應(yīng)用程序線程,等待垃圾回收的完成)
  • Mixed GC 新生代 + 老年代部分區(qū)域的垃圾回收,G1 收集器特有
  • FullGC 新生代 + 老年代完整垃圾回收,暫停時(shí)間長(STW),應(yīng)盡力避免

JVM垃圾回收器有哪些

在JVM中,實(shí)現(xiàn)了多種垃圾收集器,包括:

  • 串行垃圾收集器
  • 并行垃圾收集器
  • CMS(并發(fā))垃圾收集器
  • G1垃圾收集器

串行垃圾收集器

Serial和Serial Old串行垃圾收集器,是指使用單線程進(jìn)行垃圾回收,堆內(nèi)存較小,適合個(gè)人電腦

  • Serial作用于新生代,曹勇復(fù)制算法
  • Serial Old作用于年輕代,采用標(biāo)記-整理算法

垃圾回收時(shí),只有一個(gè)線程在工作,并且Java應(yīng)用中所有線程都要暫停(STW),等待垃圾回收的完成

并行垃圾收集器

Parallel New和Parallel Old是一個(gè)并行垃圾回收器,JDK8默認(rèn)使用此垃圾回收器

  • Parallel New作用于新生代,采用復(fù)制算法
  • Parallel Old作用于老年代,采用標(biāo)記-整理算法

垃圾回收時(shí),多個(gè)線程在工作,并且java應(yīng)用中的所有線程都要暫停(STW), 等待垃圾回收的完成

CMS(并發(fā))垃圾收集器

CMS全稱 Concurrent Mark Sweep,是一款并發(fā)的、使用標(biāo)記-清除算法的垃圾回收器,該回收器是針對老年代垃圾回收的,是一款以獲取最短回收停頓時(shí)間為目標(biāo)的收集器,停頓時(shí)間短,用戶體驗(yàn)就好。其最大特點(diǎn)是在進(jìn)行垃圾回收時(shí),應(yīng)用仍然能正常運(yùn)行

G1垃圾收集器

應(yīng)用于新生代和老年代,在JDK9之后默認(rèn)人使用的G1垃圾收集器。其中劃分了很多個(gè)區(qū)域,每個(gè)區(qū)域都可以充當(dāng)eden,survivor,old,humongous,其中humongous專門為大對象準(zhǔn)備的。采用的復(fù)制算法,并且注重于響應(yīng)時(shí)間和吞吐量。運(yùn)行時(shí)主要是分為三個(gè)階段:新生代回收、并發(fā)標(biāo)記、混合收集。如果出現(xiàn)并發(fā)失?。椿厥账俣融s不上創(chuàng)建新對象的速度),就會觸發(fā)Full GC

下面來詳細(xì)的講解一下年輕代垃圾回收:

初始的時(shí)候,所有的區(qū)域都處于空閑狀態(tài)

創(chuàng)建了一些對象,挑出一些空閑區(qū)域作為eden區(qū)存儲這些對象

當(dāng)eden區(qū)需要垃圾回收時(shí),挑出一個(gè)空閑區(qū)域作為survivor,用復(fù)制算法復(fù)制存活對象,需要暫停用戶線程

隨著時(shí)間流逝,eden區(qū)的內(nèi)存又有不足,將eden區(qū)以及之前幸存區(qū)中存活的對象,采用復(fù)制算法,復(fù)制到新的幸存區(qū),其中比較老的對象晉升至老年代

下面來說一下下一個(gè)階段年輕代垃圾回收 + 并發(fā)標(biāo)記:

當(dāng)老年代占用內(nèi)存超過一定的閾值(默認(rèn)是45%)后,觸發(fā)并發(fā)標(biāo)記,這個(gè)時(shí)候無需暫停用戶線程

并發(fā)標(biāo)記之后,會有重新標(biāo)記階段解決漏標(biāo)問題,此時(shí)需要暫停用戶線程

這些都完成后就知道了老年代有哪些存活對象,隨后進(jìn)入混合收集階段。此時(shí)不會對所有老年代區(qū)域進(jìn)行回收,而是根據(jù)暫停時(shí)間目標(biāo)優(yōu)先回收價(jià)值高 (存活對象少)的區(qū)域(這也是 Gabage First 名稱的由來)

混合垃圾回收的執(zhí)行流程:

復(fù)制完成,內(nèi)存得到釋放。進(jìn)入到下一輪的新生代回收、并發(fā)標(biāo)記、混合收集

其中H叫做大對象,如果對象非常大,就會開辟一塊連續(xù)的空間存儲巨型對象

強(qiáng)引用與軟引用與弱引用與虛引用的區(qū)別

強(qiáng)引用:只有所有 GC Roots 對象都不通過【強(qiáng)引用】引用該對象,該對象才能 被垃圾回收

User user = new User()

軟引用:僅有軟引用引用該對象時(shí),在垃圾回收后,內(nèi)存仍不足時(shí)會再次出發(fā)垃圾回收

User user = new User();
SoftReference softReference = new SoftReference(user);

弱引用:僅有弱引用引用該對象時(shí),在垃圾回收時(shí),無論內(nèi)存是否充足,都會回收弱引用對象

User user = new User();
WeakReference weakReference = new WeakReference(user);

虛引用:必須配合引用隊(duì)列使用,被引用對象回收時(shí),會將虛引用入隊(duì),由Reference Handler線程調(diào)用虛引用相關(guān)方法釋放直接內(nèi)存

User user = new User();
ReferenceQueue referenceQueue = new ReferenceQueue();
PhantomReference phantomReference = new PhantomReference(user,queue);

到此這篇關(guān)于JVM垃圾回收機(jī)制和垃圾回收器詳細(xì)解說的文章就介紹到這了,更多相關(guān)JVM垃圾回收內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java8新特性Stream流實(shí)例詳解

    Java8新特性Stream流實(shí)例詳解

    Stream流是數(shù)據(jù)渠道,用于操作數(shù)據(jù)源(集合、數(shù)組等)所生成的元素序列。這篇文章主要介紹了Java8新特性Stream流的相關(guān)資料,需要的朋友參考下吧
    2017-10-10
  • Spring實(shí)戰(zhàn)之Qualifier注解用法示例

    Spring實(shí)戰(zhàn)之Qualifier注解用法示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之Qualifier注解用法,結(jié)合實(shí)例形式詳細(xì)分析了spring Qualifier注解相關(guān)配置、定義與使用方法,需要的朋友可以參考下
    2019-12-12
  • Java?Validated?分組校驗(yàn)的使用

    Java?Validated?分組校驗(yàn)的使用

    這篇文章主要介紹了Java?Validated?分組校驗(yàn)的使用,文章記錄所以在這里記錄下分組校驗(yàn)注解@Validated的使用,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-02-02
  • Java實(shí)現(xiàn)簡易俄羅斯方塊

    Java實(shí)現(xiàn)簡易俄羅斯方塊

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡易俄羅斯方塊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Java中Struts2的值棧ValueStack詳解

    Java中Struts2的值棧ValueStack詳解

    這篇文章主要介紹了Java中Struts2的值棧ValueStack詳解,值棧(ValueStack)就是 OGNL 表達(dá)式存取數(shù)據(jù)的地方,在一個(gè)值棧中,封裝了一次請求所需要的所有數(shù)據(jù),需要的朋友可以參考下
    2023-08-08
  • IDEA正則表達(dá)式全局搜索圖文教程

    IDEA正則表達(dá)式全局搜索圖文教程

    當(dāng)您要搜索和替換特定的文本模式時(shí),請使用正則表達(dá)式,下面這篇文章主要給大家介紹了關(guān)于IDEA正則表達(dá)式全局搜索的相關(guān)資料,文中通過代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • Java檢查非空的三種方法總結(jié)

    Java檢查非空的三種方法總結(jié)

    這篇文章主要介紹了Java檢查非空的三種方法總結(jié),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 一道關(guān)于java異常處理的題目

    一道關(guān)于java異常處理的題目

    本文給大家分享一道關(guān)于java異常處理的題目,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • Java實(shí)現(xiàn)的二叉樹常用操作【前序建樹,前中后遞歸非遞歸遍歷及層序遍歷】

    Java實(shí)現(xiàn)的二叉樹常用操作【前序建樹,前中后遞歸非遞歸遍歷及層序遍歷】

    這篇文章主要介紹了Java實(shí)現(xiàn)的二叉樹常用操作,包括二叉樹的前序建樹,前中后遞歸非遞歸遍歷及層序遍歷等相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • SpringBoot事件監(jiān)聽器@EventListener的實(shí)現(xiàn)

    SpringBoot事件監(jiān)聽器@EventListener的實(shí)現(xiàn)

    @EventListener注解用于處理應(yīng)用程序事件,提供了一種方便的方式來監(jiān)聽和響應(yīng)各種事件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11

最新評論

克什克腾旗| 和林格尔县| 盘锦市| 法库县| 慈利县| 巴林左旗| 陕西省| 石棉县| 故城县| 天柱县| 剑川县| 宜丰县| 平罗县| 五河县| 田东县| 华蓥市| 平罗县| 湟源县| 噶尔县| 常州市| 祁东县| 舞阳县| 肃北| 临漳县| 荔波县| 台北市| 留坝县| 邯郸市| 铅山县| 威远县| 诸城市| 疏勒县| 南木林县| 山西省| 平原县| 五大连池市| 巴林右旗| 东乌珠穆沁旗| 湖口县| 武功县| 二连浩特市|