欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

什么是垃圾回收機制

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

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

對象什么時候可以被垃圾回收

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

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

引用計數(shù)法

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

String demo = new String("123");

String demo = null;

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

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

引用計數(shù)法的優(yōu)點:

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

缺點:

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

可達(dá)性分析算法

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

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

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

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

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

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

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

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

JVM垃圾回收算法有哪些

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

標(biāo)記清除算法

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

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

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

  • 效率比較低,標(biāo)記和清除兩個動作都是需要遍歷所有的對象,并且GC的時候,需要停止應(yīng)用程序,對于交互性要求比較高的應(yīng)用而言這個不是很推薦
  • (重要)通過標(biāo)記清除算法清理出來的內(nèi)存,碎片化比較嚴(yán)重,因為被回收的對象可能存在于內(nèi)存的各個角落,所以清理出來的內(nèi)存不是很連貫

復(fù)制算法

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

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

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

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

優(yōu)點:

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

缺點:

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

標(biāo)記整理算法

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

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

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

優(yōu)缺點:

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

分代收集算法

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

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

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

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

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

經(jīng)過一段時間之后,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ā)生在新生代的垃圾回收,暫停時間短(STW:暫停所有應(yīng)用程序線程,等待垃圾回收的完成)
  • Mixed GC 新生代 + 老年代部分區(qū)域的垃圾回收,G1 收集器特有
  • FullGC 新生代 + 老年代完整垃圾回收,暫停時間長(STW),應(yīng)盡力避免

JVM垃圾回收器有哪些

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

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

串行垃圾收集器

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

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

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

并行垃圾收集器

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

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

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

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

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

G1垃圾收集器

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

User user = new User()

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

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

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

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

虛引用:必須配合引用隊列使用,被引用對象回收時,會將虛引用入隊,由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垃圾回收機制和垃圾回收器詳細(xì)解說的文章就介紹到這了,更多相關(guān)JVM垃圾回收內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot解決yml明文密碼問題的方法

    SpringBoot解決yml明文密碼問題的方法

    在現(xiàn)代的軟件開發(fā)中,安全性是一個重要的考量因素,對于使用SpringBoot框架開發(fā)的應(yīng)用程序而言,敏感信息如數(shù)據(jù)庫密碼、API密鑰等通常存儲在YAML配置文件中,而這些文件往往是明文存儲,存在安全隱患,所以本文介紹了SpringBoot解決yml明文密碼問題的方法
    2024-07-07
  • Java從控制臺接受輸入字符的簡單方法

    Java從控制臺接受輸入字符的簡單方法

    這篇文章主要介紹了Java從控制臺接受輸入字符的簡單方法,需要的朋友可以參考下
    2014-02-02
  • springboot項目開啟https協(xié)議的項目實現(xiàn)

    springboot項目開啟https協(xié)議的項目實現(xiàn)

    本文主要介紹了springboot項目開啟https協(xié)議的項目實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • springboot使用com.github.binarywang包實現(xiàn)微信網(wǎng)頁上的支付和退款

    springboot使用com.github.binarywang包實現(xiàn)微信網(wǎng)頁上的支付和退款

    最近做項目需要實現(xiàn)在pc端需要實現(xiàn)微信的支付,本文主要介紹了springboot使用com.github.binarywang包實現(xiàn)微信網(wǎng)頁上的支付和退款,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • Java sha1散列算法原理及代碼實例

    Java sha1散列算法原理及代碼實例

    這篇文章主要介紹了Java sha1散列算法原理及代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • maven多個plugin相同phase的執(zhí)行順序

    maven多個plugin相同phase的執(zhí)行順序

    這篇文章主要介紹了maven多個plugin相同phase的執(zhí)行順序,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Java實現(xiàn)定時任務(wù)的示例代碼

    Java實現(xiàn)定時任務(wù)的示例代碼

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)定時任務(wù)的相關(guān)知識,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-11-11
  • 解決Springboot項目打包后的頁面丟失問題(thymeleaf報錯)

    解決Springboot項目打包后的頁面丟失問題(thymeleaf報錯)

    這篇文章主要介紹了解決Springboot項目打包后的頁面丟失問題(thymeleaf報錯),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java如何通過IP解析地理位置

    java如何通過IP解析地理位置

    這篇文章主要介紹了java如何通過IP解析地理位置的實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Spring Security實現(xiàn)微信公眾號網(wǎng)頁授權(quán)功能

    Spring Security實現(xiàn)微信公眾號網(wǎng)頁授權(quán)功能

    這篇文章主要介紹了Spring Security中實現(xiàn)微信網(wǎng)頁授權(quán),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08

最新評論