<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 分代收集理論 ### 3個假說 * 弱分代假說:絕大多數對象都是朝生夕滅的。(設計了年輕代) * 強分代假說:熬過越多次垃圾收集過程的對象就越難以消亡。(設計了老年代) * 跨代引用假說:跨代引用相對于同代引用僅占極少數。(實際Java應用中,可能會存在年輕代的對象跨代引用了老年代的對象)(設計了`記憶集`,在新生代上建立全局的記憶集,把老年代劃分為若干個小塊,標識出老年代的哪一塊內存會存在跨代引用,此后在Minor GC時,只有包含了跨代引用的小塊內存里的對象才會被加入到GC Roots進行掃描) ### 分代實現 ![](https://img.kancloud.cn/24/13/241383bdd98b8d68858b9fe1586268ba_1252x516.png) HotSpot虛擬機中,根據對象存活周期的不同,將內存劃分為幾塊。一般是將Java堆分為新生代和老年代,比例為`2:1`;新生代又細分為`Eden`區、`From Survivor`區和`To Survivor`區,比例為`8:1:1`。不同的代采用不同的回收算法: * 新生代:復制算法 * 老年代:標記-清除算法,或者標記-整理算法 ### 定義一些關于GC的名詞 1. 部分收集(Partial GC): 不是完整收集Java堆的收集。 * 新生代收集(Minor GC/Young GC):只是新生代的收集。 * 老年代收集(Major GC/Old GC):只是老年代的收集。目前只有CMS收集器會有單獨收集老年代的行為。 * 混合收集(Mixed GC):收集整個新生代以及部分老年代的垃圾收集。目前只有G1收集器會有這種行為。 2. 整堆收集(Full GC):收集整個Java堆和方法區的垃圾收集。 ## 垃圾收集算法 知道了如何判定**無用的對象**、**廢棄常量**和**無用的類**后,接下來就是將這些無用的對象給回收掉。 如下是常用的3種垃圾收集算法。 ### 標記-清除 ![](https://img.kancloud.cn/73/5a/735a6efe6ff6caf8f94af147e5e4c4dc_1620x980.png) 該算法分為標記和清除兩個階段。 * 標記:遍歷所有的 GC Roots,然后將所有 GC Roots 可達的對象標記為存活的對象。 * 清除:遍歷堆中所有的對象,將沒有標記的對象清除掉。同時清除對象上的標記,以便下一次垃圾回收。 這種方法有2個不足: 1. 效率問題:標記和清除2個過程效率都不高 2. 空間問題:回收后內存會有大量碎片;碎片太多可能導致以后需要分配大對象時,無法找到足夠連續的內存不得不提前觸發另一次垃圾回收動作。 ### 復制(新生代) ![](https://img.kancloud.cn/1b/8b/1b8bf2a00f285696149f4d3a2e633613_1618x978.png) 為了解決效率問題,復制算法出現了。它將可用內存按容量劃分為大小相同的兩塊,每次只使用其中的一塊。當這一塊內存用完,需要進行垃圾收集時,就將存活的對象復制到另一塊上,然后清除掉這一塊內存。 這種算法有優有劣: * 優勢:不會產生碎片。 * 劣勢:內存縮小為原來的一般,浪費空間。 **為了解決空間利用率問題**,可以將內存分為3塊:Eden、From Survivor、To Survivor,比例是8:1:1,每次使用Eden和其中一塊Survivor。回收時,將Eden和Survivor中存活的對象一次性復制到另一塊Survivor空間上,最后清理掉Eden和剛才使用的Survivor空間。這樣只有10%的內存被浪費。 但是無法保證每次回收都只有不多于10%的對象存活,當Survivor空間不足時,需要依賴其他內存(老年代)進行**分配擔保**。 **分配擔保**是指如果另一塊Survivor空間沒有足夠空間存放上一次新生代收集下來的存活對象時(超過10%),這些對象將直接通過分配擔保機制進入老年代。 ### 標記-整理(老年代) ![](https://img.kancloud.cn/43/93/4393cc6bc80aa5131f1dfefa74939856_1612x984.png) 該算法分為標記和整理兩個階段。 * 標記:遍歷所有的 GC Roots,然后將所有 GC Roots 可達的對象標記為存活的對象。(和標記-清除的標記階段一樣) * 整理:移動所有存活的對象,按著內存地址次序依次排列,然后將末端地址以后的全部內存回收。 這是一種老年代的收集算法,老年代的對象存活時間比較長。 ## 參考資料 * 周志明 * 《深入理解Java虛擬機》 * Java虛擬機底層原理知識總結 * https://doocs.github.io/jvm/
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看