JVM 垃圾回收算法

    1 Java垃圾回收機制(GC是什么?為什么要GC) 為了讓程序員更專注于代碼的實現,而不用過多的考慮內存釋放的問題,所以,在Java語言中,有了自動的垃圾回收機制,也就是我們熟悉的

    1 Java垃圾回收機制(GC是什么?為什么要GC)

    ? 為了讓程序員更專注于代碼的實現,而不用過多的考慮內存釋放的問題,所以,在Java語言中,有了自動的垃圾回收機制,也就是我們熟悉的GC(Garbage Collection)。

    有了垃圾回收機制后,程序員只需要關心內存的申請即可,內存的釋放由系統自動識別完成。

    在進行垃圾回收時,不同的對象引用類型,GC會采用不同的回收時機

    換句話說,自動的垃圾回收的算法就會變得非常重要了,如果因為算法的不合理,導致內存資源一直沒有釋放,同樣也可能會導致內存溢出的。

    當然,除了Java語言,C#、Python等語言也都有自動的垃圾回收機制。

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

    JVM 垃圾回收算法_垃圾回收

    簡單一句就是:如果一個或多個對象沒有任何的引用指向它了,那么這個對象現在就是垃圾,如果定位了垃圾,則有可能會被垃圾回收器回收。

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

    2.1 引用計數法

    一個對象被引用了一次,在當前的對象頭上遞增一次引用次數,如果這個對象的引用次數為0,代表這個對象可回收

    String demo = new String("123");

    JVM 垃圾回收算法_垃圾收集器_02

    String demo = null;

    JVM 垃圾回收算法_jvm_03

    當對象間出現了循環引用的話,則引用計數法就會失效

    JVM 垃圾回收算法_垃圾收集器_04

    先執行右側代碼的前4行代碼

    JVM 垃圾回收算法_jvm_05

    目前上方的引用關系和計數都是沒問題的,但是,如果代碼繼續往下執行,如下圖

    JVM 垃圾回收算法_jvm_06

    雖然a和b都為null,但是由于a和b存在循環引用,這樣a和b永遠都不會被回收。

    優點:

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

    缺點:

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

    2.2 可達性分析算法

    現在的虛擬機采用的都是通過可達性分析算法來確定哪些內容是垃圾。

    會存在一個根節點【GC Roots】,引出它下面指向的下一個節點,再以下一個節點節點開始找出它下面的節點,依次往下類推。直到所有的節點全部遍歷完畢。

    根對象是那些肯定不能當做垃圾回收的對象,就可以當做根對象

    局部變量,靜態方法,靜態變量,類信息

    核心是:判斷某對象是否與根對象有直接或間接的引用,如果沒有被引用,則可以當做垃圾回收

    JVM 垃圾回收算法_垃圾回收_07

    X,Y這兩個節點是可回收的,但是并不會馬上的被回收??!?對象中存在一個方法【finalize】。當對象被標記為可回收后,當發生GC時,首先會判斷這個對象是否執行了finalize方法,如果這個方法還沒有被執行的話,那么就會先來執行這個方法,接著在這個方法執行中,可以設置當前這個對象與GC ROOTS產生關聯,那么這個方法執行完成之后,GC會再次判斷對象是否可達,如果仍然不可達,則會進行回收,如果可達了,則不會進行回收。

    finalize方法對于每一個對象來說,只會執行一次。如果第一次執行這個方法的時候,設置了當前對象與RC ROOTS關聯,那么這一次不會進行回收。 那么等到這個對象第二次被標記為可回收時,那么該對象的finalize方法就不會再次執行了。

    GC ROOTS:

    • 虛擬機棧(棧幀中的本地變量表)中引用的對象
    /**
     * demo是棧幀中的本地變量,當 demo = null 時,由于此時 demo 充當了 GC Root 的作用,demo與原來指向的實例 new Demo() 斷開了連接,對象被回收。
     */
    public class Demo {
        public static  void main(String[] args) {
         Demo demo = new Demo();
         demo = null;
        }
    }
    • 方法區中類靜態屬性引用的對象
    /**
     * 當棧幀中的本地變量 b = null 時,由于 b 原來指向的對象與 GC Root (變量 b) 斷開了連接,所以 b 原來指向的對象會被回收,而由于我們給 a 賦值了變量的引用,a在此時是類靜態屬性引用,充當了 GC Root 的作用,它指向的對象依然存活!
     */
    public class Demo {
        public static Demo a;
        public static  void main(String[] args) {
            Demo b = new Demo();
            b.a = new Demo();
            b = null;
        }
    }
    • 方法區中常量引用的對象
    /**
     * 常量 a 指向的對象并不會因為 demo 指向的對象被回收而回收
     */
    public class Demo {
        
        public static final Demo a = new Demo();
        
        public static  void main(String[] args) {
            Demo demo = new Demo();
            demo = null;
        }
    }
    • 本地方法棧中 JNI(即一般說的 Native 方法)引用的對象

    3 JVM 垃圾回收算法有哪些?

    3.1 標記清除算法

    標記清除算法:是將垃圾回收分為2個階段,分別是標記和清除。

    1.根據可達性分析算法得出的垃圾進行標記

    2.對這些標記為可回收的內容進行垃圾回收

    JVM 垃圾回收算法_垃圾回收_08

    可以看到,標記清除算法解決了引用計數算法中的循環引用的問題,沒有從root節點引用的對象都會被回收。

    同樣,標記清除算法也是有缺點的:

    • 效率較低,標記和清除兩個動作都需要遍歷所有的對象,并且在GC時,需要停止應用程序,對于交互性要求比較高的應用而言這個體驗是非常差的。
    • (重要)通過標記清除算法清理出來的內存,碎片化較為嚴重,因為被回收的對象可能存在于內存的各個角落,所以清理出來的內存是不連貫的。

    3.2 復制算法

    復制算法的核心,將原有的內存空間一分為二,每次只用其中的一塊,在垃圾回收時,將正在使用的對象復制到另一個內存空間中,然后將該內存空間清空,交換兩個內存的角色,完成垃圾的回收。

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

    JVM 垃圾回收算法_垃圾回收_09

    1)將內存區域分成兩部分,每次操作其中一個。

    2)當進行垃圾回收時,將正在使用的內存區域中的存活對象移動到未使用的內存區域。當移動完對這部分內存區域一次性清除。

    3)周而復始。

    優點:

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

    缺點:

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

    3.3 標記整理算法

    標記壓縮算法:是在標記清除算法的基礎之上,做了優化改進的算法。和標記清除算法一樣,也是從根節點開始,對對象的引用進行標記,在清理階段,并不是簡單的直接清理可回收對象,而是將存活對象都向內存另一端移動,然后清理邊界以外的垃圾,從而解決了碎片化的問題。

    JVM 垃圾回收算法_jvm_10

    1)標記垃圾。

    2)需要清除向右邊走,不需要清除的向左邊走。

    3)清除邊界以外的垃圾。

    優缺點同標記清除算法,解決了標記清除算法的碎片化的問題,同時,標記壓縮算法多了一步,對象移動內存位置的步驟,其效率也有有一定的影響。

    與復制算法對比:復制算法標記完就復制,但標記整理算法得等把所有存活對象都標記完畢,再進行整理

    4 分代收集算法

    4.1 概述

    在java8時,堆被分為了兩份:新生代和老年代【1:2】,在java7時,還存在一個永久代。

    JVM 垃圾回收算法_jvm_11

    對于新生代,內部又被分為了三個區域。Eden區,S0區,S1區【8:1:1】

    當對新生代產生GC:MinorGC【young GC】

    當對老年代代產生GC:Major GC

    當對新生代和老年代產生FullGC: 新生代 + 老年代完整垃圾回收,暫停時間長,應盡力避免

    4.2工作機制

    JVM 垃圾回收算法_垃圾收集器_12

    • 新創建的對象,都會先分配到eden區

    JVM 垃圾回收算法_垃圾回收_13

    • 當伊甸園內存不足,標記伊甸園與 from(現階段沒有)的存活對象
    • 將存活對象采用復制算法復制到 to 中,復制完畢后,伊甸園和 from 內存都得到釋放

    JVM 垃圾回收算法_垃圾收集器_14

    • 經過一段時間后伊甸園的內存又出現不足,標記eden區域to區存活的對象,將存活的對象復制到from區

    JVM 垃圾回收算法_垃圾回收_15

    JVM 垃圾回收算法_垃圾回收_16

    • 當幸存區對象熬過幾次回收(最多15次),晉升到老年代(幸存區內存不足或大對象會導致提前晉升)

    MinorGC、 Mixed GC 、 FullGC的區別是什么

    JVM 垃圾回收算法_垃圾收集器_17

    • MinorGC【young GC】發生在新生代的垃圾回收,暫停時間短(STW)
    • Mixed GC 新生代 + 老年代部分區域的垃圾回收,G1 收集器特有
    • FullGC: 新生代 + 老年代完整垃圾回收,暫停時間長(STW),應盡力避免?

    名詞解釋:

    STW(Stop-The-World):暫停所有應用程序線程,等待垃圾回收的完成

    5 說一下 JVM 有哪些垃圾回收器?

    在jvm中,實現了多種垃圾收集器,包括:

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

    5.1 串行垃圾收集器

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

    • Serial 作用于新生代,采用復制算法
    • Serial Old 作用于老年代,采用標記-整理算法

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

    JVM 垃圾回收算法_jvm_18

    5.2 并行垃圾收集器

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

    • Parallel New作用于新生代,采用復制算法
    • Parallel Old作用于老年代,采用標記-整理算法

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

    JVM 垃圾回收算法_垃圾收集器_19

    5.3 CMS(并發)垃圾收集器

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

    JVM 垃圾回收算法_垃圾回收_20

    JVM 垃圾回收算法_垃圾收集器_21

    6 詳細聊一下G1垃圾回收器

    6.1 概述

    • 應用于新生代和老年代,在JDK9之后默認使用****G1
    • 劃分成多個區域,每個區域都可以充當 eden,survivor,old, humongous,其中 humongous 專為大對象準備
    • 采用復制算法
    • 響應時間與吞吐量兼顧
    • 分成三個階段:新生代回收、并發標記、混合收集
    • 如果并發失?。椿厥账俣融s不上創建新對象速度),會觸發 Full GC

    JVM 垃圾回收算法_垃圾收集器_22

    image-20230506154323950

    6.2 Young Collection(年輕代垃圾回收)

    • 初始時,所有區域都處于空閑狀態
    • JVM 垃圾回收算法_垃圾收集器_23


    • 創建了一些對象,挑出一些空閑區域作為伊甸園區存儲這些對象
    • JVM 垃圾回收算法_jvm_24


    • 當伊甸園需要垃圾回收時,挑出一個空閑區域作為幸存區,用復制算法復制存活對象,需要暫停用戶線程
    • JVM 垃圾回收算法_垃圾回收_25

      JVM 垃圾回收算法_垃圾回收_26


    • 隨著時間流逝,伊甸園的內存又有不足
    • 將伊甸園以及之前幸存區中的存活對象,采用復制算法,復制到新的幸存區,其中較老對象晉升至老年代
    • JVM 垃圾回收算法_垃圾收集器_27

      JVM 垃圾回收算法_垃圾收集器_28

      JVM 垃圾回收算法_垃圾回收_29


    6.3 Young Collection + Concurrent Mark (年輕代垃圾回收+并發標記)

    當老年代占用內存超過閾值(默認是45%)后,觸發并發標記,這時無需暫停用戶線程

    JVM 垃圾回收算法_垃圾回收_30

    • 并發標記之后,會有重新標記階段解決漏標問題,此時需要暫停用戶線程。
    • 這些都完成后就知道了老年代有哪些存活對象,隨后進入混合收集階段。此時不會對所有老年代區域進行回收,而是根據暫停時間目標優先回收價值高(存活對象少)的區域(這也是 Gabage First 名稱的由來)。
    • JVM 垃圾回收算法_垃圾回收_31


    6.4 Mixed Collection (混合垃圾回收)

    復制完成,內存得到釋放。進入下一輪的新生代回收、并發標記、混合收集

    JVM 垃圾回收算法_垃圾收集器_32

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

    JVM 垃圾回收算法_垃圾收集器_33

    7. JVM 垃圾回收

    提問:簡述Java垃圾回收機制?(GC是什么?為什么要GC)

    解答:

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

    有了垃圾回收機制后,程序員只需要關心內存的申請即可,內存的釋放由系統自動識別完成。

    在進行垃圾回收時,不同的對象引用類型,GC會采用不同的回收時機

    提問:對象什么時候可以被垃圾器回收

    解答:

    如果一個或多個對象沒有任何的引用指向它了,那么這個對象現在就是垃圾,如果定位了垃圾,則有可能會被垃圾回收器回收。

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

    通常都使用可達性分析算法來確定是不是垃圾

    提問: JVM 垃圾回收算法有哪些?

    解答:

    我記得一共有四種,分別是標記清除算法、復制算法、標記整理算法、分代回收

    提問: 你能詳細聊一下分代回收嗎?

    解答:

    關于分代回收是這樣的

    在java8時,堆被分為了兩份:新生代和老年代,它們默認空間占用比例是1:2

    對于新生代,內部又被分為了三個區域。Eden區,S0區,S1區默認空間占用比例是8:1:1

    具體的工作機制是有些情況:

    1)當創建一個對象的時候,那么這個對象會被分配在新生代的Eden區。當Eden區要滿了時候,觸發YoungGC。

    2)當進行YoungGC后,此時在Eden區存活的對象被移動到S0區,并且當前對象的年齡會加1,清空Eden區。

    3)當再一次觸發YoungGC的時候,會把Eden區中存活下來的對象和S0中的對象,移動到S1區中,這些對象的年齡會加1,清空Eden區和S0區。

    4)當再一次觸發YoungGC的時候,會把Eden區中存活下來的對象和S1中的對象,移動到S0區中,這些對象的年齡會加1,清空Eden區和S1區。

    5)對象的年齡達到了某一個限定的值(默認15歲?

    當然也有特殊情況,如果進入Eden區的是一個大對象,在觸發YoungGC的時候,會直接存放到老年代

    當老年代滿了之后,觸發FullGC。FullGC同時回收新生代和老年代,當前只會存在一個FullGC的線程進行執行,其他的線程全部會被掛起。 ?我們在程序中要盡量避免FullGC的出現。

    提問:講一下新生代、老年代、永久代的區別?

    解答:

    新生代主要用來存放新生的對象。

    老年代主要存放應用中生命周期長的內存對象。

    永久代指的是永久保存區域。主要存放Class和Meta(元數據)的信息。在Java8中,永久代已經被移除,取而代之的是一個稱之為“元數據區”(元空間)的區域。元空間和永久代類似,不過元空間與永久代之間最大的區別在于:元空間并不在虛擬機中,而是使用本地內存。因此,默認情況下,元空間的大小僅受本地內存的限制。

    提問:說一下 JVM 有哪些垃圾回收器?

    解答:

    在jvm中,實現了多種垃圾收集器,包括:串行垃圾收集器、并行垃圾收集器(JDK8默認)、CMS(并發)垃圾收集器、G1垃圾收集器(JDK9默認)

    提問:Minor GC、Major GC、Full GC是什么

    解答:

    嗯,其實它們指的是不同代之間的垃圾回收

    Minor GC 發生在新生代的垃圾回收,暫停時間短

    Major GC 老年代區域的垃圾回收,老年代空間不足時,會先嘗試觸發Minor GC。Minor GC之后空間還不足,則會觸發Major GC,Major GC速度比較慢,暫停時間長

    Full GC 新生代 + 老年代完整垃圾回收,暫停時間長,應盡力避免

    聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
    發表評論
    更多 網友評論0 條評論)
    暫無評論

    返回頂部

    主站蜘蛛池模板: 国产一区二区三区在线免费观看| 天天爽夜夜爽人人爽一区二区| 亚洲国产精品第一区二区三区| 亚洲色精品vr一区二区三区 | 亚洲第一区精品观看| 国产成人精品日本亚洲专一区| 中文字幕一区二区日产乱码| 精品一区二区三区影院在线午夜| 国产精品高清一区二区人妖| 国产精品视频一区二区三区四| 一区二区高清视频在线观看| 日韩在线观看一区二区三区| 欧美亚洲精品一区二区| 亚洲av日韩综合一区二区三区| 影音先锋中文无码一区| 日韩精品区一区二区三VR| 亚洲国产精品一区二区成人片国内 | AV无码精品一区二区三区| 国产AV一区二区三区传媒| 国精无码欧精品亚洲一区| 国产自产V一区二区三区C| 中文字幕一区二区三区在线播放| 好吊视频一区二区三区| 成人乱码一区二区三区av| 亚洲午夜福利AV一区二区无码| 亚洲毛片αv无线播放一区| 国产色综合一区二区三区| 日韩精品一区二区三区大桥未久| 久久99国产精一区二区三区| 一区二区三区日韩| 成人免费观看一区二区| 少妇人妻精品一区二区| 蜜桃视频一区二区三区| 丰满人妻一区二区三区免费视频| 中文人妻av高清一区二区| 亚洲高清美女一区二区三区| 伊人色综合网一区二区三区 | 欧美av色香蕉一区二区蜜桃小说| 久久久久久人妻一区二区三区| 国产天堂在线一区二区三区| 久久久久人妻精品一区三寸蜜桃 |