<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官問為什么新生代不用標記清除算法

          共 3707字,需瀏覽 8分鐘

           ·

          2021-07-26 22:09

          ????關(guān)注后回復 “進群” ,拉你進程序員交流群????

          作者丨安琪拉

          來源丨安琪拉的博客


          杭州某寫字樓,安琪拉穿著新買的19.9的皮鞋走進玻璃隔間辦公室,準備迎接一場新的表演。

          面試官 :看你簡歷上有些熟悉JVM,是吧?

          安琪拉:是的

          面試官 :那你跟我講講堆內(nèi)存的分區(qū)。

          安琪拉:[心想]:這很easy嘛,來,算是回顧一下JVM的基礎(chǔ)知識。

          我們知道堆分為新生代和老年代,新生代就是我們說的Yong Generation,老年代是 Old Generation。

          面試官 :然后呢?

          安琪拉:然后什么?

          面試官 :講完啦?下面沒有啦?新生代呢?

          安琪拉:你想聽你可以跟我說嘛,你不說我怎么知道你想聽。

          新生代又分為Eden區(qū)和Survivor區(qū),Survivor由From區(qū)域和To區(qū)域組成,完整的內(nèi)存結(jié)構(gòu),我給你畫一下,別抽了,筆遞給我一下,我畫一下,如下圖所示。

          面試官 :哦,圖可以,那為什么堆要分新生代和老年代呢?

          安琪拉:當然是為了更有效的管理內(nèi)存。

          面試官 :怎么說?

          安琪拉:假設(shè)一下,如果不分新老代,內(nèi)存就一整塊,垃圾收集器每次都要把那些長期存在的對象,和生命周期很短的對象放在一起回收,一般長生命周期的對象可能跟應用生命周期一致,你基本回收不掉的,比如Spring 框架里面的Bean管理相關(guān)的對象(ApplicationContext),整個應用運行期間都存在,這種一般經(jīng)過幾次回收最后都放在老年代,但是如果不區(qū)分新老代,每次都一起回收,性能消耗很大。

          區(qū)分新老代之后,老年代放長期存活的對象,新生代就放生命周期短的對象,老年代對象很穩(wěn)定,新生代回收不影響老年代,回收效率能大大提高。

          面試官 :那為什么新生代還要分Eden、From、To區(qū)域呢?

          安琪拉:[開始慢慢有點意思了]

          首先大部分對象生命周期是很短的,如果新生代不分多個區(qū)域,新生代可能會有二種回收方案

          第一種可能:每次回收都在新生代整塊內(nèi)存上進行,完整的垃圾回收過程分三步:

          1. 需要先找到需要清理的對象標記;
          2. 清理這些被標記的對象;
          3. 移動剩下的對象,對達到老年代晉升年齡的對象移動到老年代。

          對象被回收掉后會產(chǎn)生很多內(nèi)存碎片(被回收的對象很多),如果要解決內(nèi)存碎片,需要移動剩下的對象(標記整理算法),整個回收流程效率很低。

          第二種可能:如果沒有Survivor區(qū)(From + To),Minor GC(新生代回收)過程中,存活的對象直接被送到老年代,這樣的話老年代很快被填滿,觸發(fā)Major GC(因為Major GC一般伴隨著Minor GC,也可以看做觸發(fā)了Full GC),F(xiàn)ull GC頻繁會影響程序的執(zhí)行和響應速度。

          新生代的回收叫Minor GC, 老年代的回收叫Major GC。

          面試官 :為什么要設(shè)置兩個Survivor區(qū)呢?From 和 To

          安琪拉:我們來看一下, 如果只有一個Survivor區(qū),新生代內(nèi)存的回收流程。

          我按照上面這張圖畫的講,第一次Eden區(qū)域滿了,內(nèi)存回收很簡單,直接把Eden區(qū)域存活對象放到Suvivor區(qū)域;

          第二次內(nèi)存回收,需要回收二個地方,Eden區(qū)域和Survivor區(qū)域。

          • 因為Survivor區(qū)域也會存活的對象需要被回收,對Survivor區(qū)要采用標記整理垃圾收集算法,(先標記需要清理的對象,然后回收,然后把剩下的存活對象放到一起);

          • Eden區(qū)域采用復制算法,把Eden區(qū)域存放的對象復制到Survivor區(qū)域,然后把整個Eden區(qū)清除。

          看到網(wǎng)上有些文章說這里設(shè)置二個Survivor區(qū)域的原因是為了避免內(nèi)存碎片,因為他假設(shè)第二次(以及后續(xù))的回收,內(nèi)存回收是先回收Eden區(qū)域,然后是Survivor區(qū)域,這樣當然會有內(nèi)存碎片,但是如果真是只有一個Survivor區(qū)域,垃圾回收設(shè)計者肯定是先回收Survivor區(qū)域,再回收Eden區(qū)域,等Survivor區(qū)回收整理好,再把Eden區(qū)存放對象搬到Survivor區(qū),這樣存活地址是連續(xù)的,沒有內(nèi)存碎片。所以真正的原因還是我下面說的效率問題。

          面試官 :這樣有什么問題呢?

          安琪拉:這樣做有幾個問題:

          1. 經(jīng)過幾次回收之后,Survivor區(qū)域滿了之后怎么辦?直接搬到老年代?那老年代很快就爆炸了。搬到Eden區(qū)?那內(nèi)存碎片產(chǎn)生了,可能Survivor區(qū)和Eden區(qū)回收完之后,還需要再整理一下內(nèi)存去掉內(nèi)存碎片,性能消耗也是很大的。
          2. 一般標記整理算法的性能消耗是比復制算法消耗要大的,尤其是在新生代98%的對象都是“朝生夕死”的,標記清楚的是98%的對象,剩下就2%對象,要整理內(nèi)存,不然直接把這2%對象放到另一個地方,把整塊內(nèi)存清除,Eden整塊內(nèi)存清除效率很高的。

          所以歸根結(jié)底,二個Survivor區(qū)還是為了性能考慮,標記復制算法效率比標記整理效率高。

          面試官 :那你跟我詳細講講標記新生代除了Eden,另外采用二個Survivor區(qū)的標記復制算法。

          安琪拉:新生代中的對象 98% 是“ 朝生夕死” 的, 所以并不需要按照 1: 1 的比例來劃分Eden和Survivor的空間, 而是將新生代分為較大的一塊Eden空間和兩塊較小的Survivor 空間,每次只使用 Eden 和 其中一塊Survivor[0](From區(qū)域),留出Survivor[1](To區(qū)域)用來實現(xiàn)標記復制。

          當回收時, 將 Eden 和 Survivor[0] 中還存活著的對象一次性地復制到另外一塊 Survivor[1] (To)空間上, 最后清理掉 Eden 和 剛才用過的 Survivor 空間。

          另外說明一點:From區(qū)域和To區(qū)域在每次Minor GC之后都會互轉(zhuǎn),F(xiàn)rom區(qū)域變成To區(qū)域,To區(qū)域變成From區(qū)域,這只是邏輯標識

          HotSpot 虛擬機默認 將Eden 和 Survivor 的大小比例是 8: 1(CMS不適用), 也就是每次新生代中可用內(nèi)存空間為整個新生代容量的 90%( 80%+ 10%),只有10%的內(nèi)存會被“ 浪費”(一直有10%的內(nèi)存(Survivor To區(qū))不存東西)。

          標記復制算法流程:

          1. Eden區(qū)域+Survivor From區(qū)滿,進行存活對象標記,標記完,把存活對象復制到Survivor To區(qū)域;
          2. Survivor To區(qū)域變成From區(qū)域(一個邏輯標識),F(xiàn)rom區(qū)域變成To區(qū)域;
          3. 內(nèi)存分配,繼續(xù)步驟1,復制過程中有達到老年代晉升年齡(默認值15),移動到老年代。

          面試官:剛才說了這么多,是不是來之前背題了?

          安琪拉:【心想】回答不出來你說我對技術(shù)沒追求,回答出來了你說我背題,WTF。。

          耐心對面試官解釋:怎么可能,我只不過是來之前把安琪拉的博客公眾號上的文章都看了一遍,嘿嘿。

          面試官:在哪看,你分享給我。

          面試官:誒誒,還有老年代內(nèi)存回收策略呢?還有標記整理算法呢?另外講講幾種常見的垃圾回收器,CMS和G1。

          安琪拉:不想講了,累了,要不放在二面的時候講吧。

          面試官:沒事,二面面試官還是我,你直接講吧。

          安琪拉:真不想講了。

          面試官:那今天先到這吧,回去等通知,您出了這個門左拐。

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

          點擊??卡片,關(guān)注后回復【面試題】即可獲取

          在看點這里好文分享給更多人↓↓

          瀏覽 13
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉久久久久久 | 欧美性成人1819 | 久久网一区二区 | 人妻无码在线视频 | 男女草逼 |