<del id="d4fwx"><form id="d4fwx"></form></del>
      <del id="d4fwx"><form id="d4fwx"></form></del><del id="d4fwx"><form id="d4fwx"></form></del>

            <code id="d4fwx"><abbr id="d4fwx"></abbr></code>
          • 2023跳槽最新面試題整理——JVM系列-創(chuàng)新互聯(lián)

            今天是農歷2022年臘月二十七了,和往常的春節(jié)假期、五一假期和十一假期一樣都是團隊中堅持到最后的一個。沒幾天也要快過年了,我先提前向大家拜個早年——祝大家兔年大吉,新春快樂,財源滾滾,萬事如意。
            今年從十一假期之后由于種種原因也沒有更新文章,今天最后一天,由于做其他的也沒有心情,那就老規(guī)劃——最后一天就自己靜下心來整理文章來和大家分享;再加上今年由于YQ放開,大家都在積蓄力量準備明年跳槽,那今天我就開始給大家來持續(xù)更新面試題系列吧,這篇文章先來更新JVM系列,打算完整的給大家整理出面試問題重點,然后再看時間是否充裕再來判斷是否給大家整理詳細問題答案。

            創(chuàng)新互聯(lián)專注于企業(yè)成都營銷網站建設、網站重做改版、龍里網站定制設計、自適應品牌網站建設、H5響應式網站、商城網站建設、集團公司官網建設、成都外貿網站制作、高端網站制作、響應式網頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為龍里等各大城市提供網站開發(fā)制作服務。1、類加載機制 ??? 1.1、類加載過程

            ?類加載過程可以初步分成如下幾步:
            ?加載—>驗證—>準備—>解析—>初始化
            在這里插入圖片描述

            • 加載: 根據類的全限定類名從磁盤獲取類的二進制字節(jié)流。
            • 驗證: 字節(jié)碼驗證、文件格式驗證、元數(shù)據驗證和符號引用驗證
            • 準備: 靜態(tài)變量分配內存并且賦予零值
            • 解析: 將在編譯階段的符號引用轉化為直接引用,直接指向其內存地址
            • 初始化: 將解析過程中的零值更改為程序員賦值的值
            1.2、類加載器分類

            ?類加載器分為:啟動類加載器、擴展類加載器、應用程序類加載器和自定義類加載器

            • 啟動類加載器(Bootstrap Class Loader): 加載< JAVA-HOME >\lib目錄下的文件
            • 擴展類加載器(Extension Class Loader): 加載< JAVA-HOME >\lib\ext目錄下的文件
            • 應用程序類加載器(Application Class Loader): 加載用戶類路徑下的所有類包,也就是用戶自己寫的類
            • 自定義類加載器(User Class Loader): 負責加載用戶自定義的類路徑下的類包
            1.3、雙親委派機制

            ?雙親委派機制流程圖如下所示:
            在這里插入圖片描述

            ? 1.3.1、雙親委派如何運行

            ? ?? ?? 這段我就用大白話來給大家講解了哈。比如當我自己寫的一個類需要加載的時候,它會先去應用程序類加載器中看是否被加載過,發(fā)現(xiàn)沒有;然后交由應用程序類加載器的父類擴展類加載器看是否被加載過,發(fā)現(xiàn)也沒有;然后它就會交由擴展類加載器的父類啟動類加載器加載,發(fā)現(xiàn)同樣也沒有,上面的這些交由父類加載器就是向上委托;此時會進行向下指派,啟動類加載器指派給它的子類擴展類加載器,擴展類加載器指派給應用程序類加載器,此時應用程序類加載器沒有向下指派的了,那么就由應用程序類加載器加載。
            ? ?? ?? 上面如果大家不太明白,你們可以根據我的上段所說的內容去畫流程圖,那么大家在畫流程圖之后就完全明白了。

            ? 1.3.2、雙親委派這種機制好處

            ? ?? ?? 采用雙親委派機制加載主要有一下兩點好處:
            ? ?? ?? 1、保證沙箱安全;比如JDK中的java.lang.String中,如果我對這個類重寫了,那么是不生效的,因為它在走到啟動類加載器的時候發(fā)現(xiàn)已經被加載了,那么就會直接返回,此時就保證了其安全。
            ? ?? ?? 2、防止重復加載

            ? 1.3.3、為什么在父類加載器沒有加載的時候為什么不自己加載,反而交給子類加載器加載?

            ? ?? ?? 如果直接直接在父類加載器加載,此時加載看著比較省事了,因為不需要再向下指派,但是在下一次需要加載的時候,又需要向上進行查找,那么是比較麻煩的,所以直接進行向下委派給子類加載器加載。

            2、JVM運行時數(shù)據區(qū)

            JVM運行時數(shù)據區(qū)主要包括堆、虛擬機棧、方法區(qū)、本地方法棧和程序計數(shù)器。
            運行時數(shù)據區(qū)圖如下所示:
            在這里插入圖片描述下面我詳細介紹下運行時數(shù)據區(qū)各個部分其功能:

            線程共享:

            • 堆: 主要存放new出來的對象,還有數(shù)組和JDK1.8存放字符串常量池;
            • 方法區(qū): 主要存放類信息、方法信息,靜態(tài)變量和常量池等等;

            線程獨享:

            • 虛擬機棧: 虛擬機棧是由一個個棧幀組成,當每調用一個方法時就是生成一個棧幀壓入虛擬機棧中,棧幀中包含局部變量、操作數(shù)棧、動態(tài)鏈接和方法出口;
            • 本地方法棧: 本地方法棧和虛擬機棧的原理一樣,只是虛擬機棧調用的是Java方法,但是本地方法棧調用的是本地方法(Native);
            • 程序計數(shù)器: 在Java程序運行過程中,會發(fā)生線程上下文切換,當線程重新獲得CPU時間片時,要保證從上次執(zhí)行的行數(shù)繼續(xù)執(zhí)行,那么程序計數(shù)器就是保證從原來位置繼續(xù)執(zhí)行;
            3、JVM對象創(chuàng)建和內存分配機制 ???????3.1、堆內存結構介紹

            ???堆內存分為新生代和老年代,新生代:老年代=1:2;新生代中又分為Eden、S0和S1區(qū);Eden:S0:S1=8:1:1;
            在這里插入圖片描述

            3.2、對象創(chuàng)建流程

            ???類加載流程如下圖所示:
            在這里插入圖片描述詳細介紹其每一步流程:
            ???1、加載: 當new對象時,會根據雙親委派機制檢查下該類是否被加載過,如果沒有加載過則執(zhí)行類加載過程:加載—>驗證—>準備—>解析—>初始化;
            ???2、分配內存: 當加載完成之后,接下來就要為新生的對象去分配內存空間;當類加載完成之后就知道了對象所需要內存空間;就從堆中找出一塊對象所需要內存空間大小的內存給該對象;
            ??????????劃分內存方法:
            ?????????????1、指針碰撞法: 如果Java堆中內存是絕對規(guī)整的,所有用過的內存都放在一邊,空閑的內存放在另一邊,中間放著一個指針作為分界點 的指示器,那所分配內存就僅僅是把那個指針向空閑空間那邊挪動一段與對象大小相等的距離。
            ?????????????2、空閑列表法: 如果Java堆中的內存并不是規(guī)整的,已使用的內存和空閑的內存相互交錯,那就沒有辦法簡單地進行指針碰撞了,虛擬機就必須維護一個列表,記錄上哪些內存塊是可用的,在分配的時候從列表中找到一塊足夠大的空間劃分給對象實例, 并更新列表上的記錄。
            ??????????解決并發(fā)分配內存產生問題:
            ??????????在并發(fā)情況下,可能出現(xiàn)正在給對象A分配內存,指針還沒來得及修改,對象B又同時使用了原來的指針來分配內存的情況。
            ??????????CAS(compare and swap)法:
            ??????????虛擬機采用CAS配上失敗重試的方式保證更新操作的原子性來對分配內存空間的動作進行同步處理。
            ???3、初始化: 內存分配完成后,虛擬機需要將分配到的內存空間都初始化為零值(不包括對象頭),這一步操作保證了對象的實例字段在Java代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數(shù)據類型所對應的零值。
            注意: 這里的初始化和加載過程的初始化是不一樣的,加載的初始化是將static修飾的靜態(tài)變量賦予零值。
            ???4、設置對象頭: 初始化零值之后,要對對象做些必要設置,例如對象屬于哪個類的實例對象,GC年齡,對象hashcode和如何找到類的元數(shù)據信息等等。
            ???在虛擬機中,對象在內存中布局分為三部分:對象頭、實例數(shù)據和對齊填充。
            ???對象頭主要包含兩部分信息:一部分是運行時自身數(shù)據:hash碼、GC年齡、偏向鎖ID,線程持有的鎖等等;另一部分是對象持有類的指針,即對象指向它類元數(shù)據的指針,虛擬機通過這個指針找到該對象歸屬于哪個類。
            在這里插入圖片描述???5、執(zhí)行init()方法:
            ????????執(zhí)行方法,即對象按照程序員的意愿進行初始化。對應到語言層面上講,就是為屬性賦值(注意,這與上面的賦零值不同,這是由程序員賦的值),和執(zhí)行構造方法。

            3.3、對象內存分配

            ???對象內存分配流程圖如下所示:
            在這里插入圖片描述
            ???一般我們認為對象會直接分配到堆中新生代Eden區(qū)中,這是不對的,對象可能分配到虛擬機棧中,也有可能分配到堆中的老年代中,這都是可能發(fā)生的。下面我來介紹下這幾種情況

            3.3.1、對象在棧上分配

            ???當對象發(fā)生了逃逸分析時,那么此時對象就會直接分配到棧中,而不是分配到堆中。這樣做的目的是能夠減少GC的壓力,因為分配到棧中之后,會隨著調用這個方法結束而出棧銷毀。
            ???什么是逃逸分析?
            ???????這個通俗講就是我在方法內部new一個對象后,該對象只在該方法中使用,不會讓方法以外的使用,那么此時就發(fā)生了逃逸分析。

            3.3.2、對象在Eden區(qū)分配

            ???正常情況下大量的對象都是分配到堆中新生代的Eden區(qū)。

            3.3.3、大對象直接分配至老年代

            ???當我們創(chuàng)建的是大對象時,會直接分配到老年代中,這樣做的的目的減少它在新生代中每次GC來回復制,并且能減少觸發(fā)minor GC次數(shù)而引發(fā)的實際不是真正長時間存活的對象而存放老年代所引發(fā)的一系列問題。
            ???大對象是如何判斷的呢?
            ????????在JVM中設置-XX:PretenureSizeThreshold 可以設置大對象的大小

            3.3.4、長期存活的對象進入老年代

            ????這種也是正常的,當對象創(chuàng)建之后放入堆中新生代的Eden區(qū),然后當新生代滿了之后觸發(fā)minor GC,每次minor GC存活的對象,他們的對象頭的GC年齡就會+1,當達到15次之后,就會講對象存放進老年代,此時就是長期存活對象進入老年代。

            3.3.5、對象動態(tài)年齡判斷

            ????當某一年齡的對象占Survivor區(qū)的一半以上時,那么他就會將大于等于它的GC年齡直接存放進老年代中。

            3.3.6、老年帶空間擔保機制

            ????當觸發(fā)minor GC的時候都會去看下老年代的可用空間大小,如果老年代的可用空間大小大于等于新生代對象所有之和,那么可以直接觸發(fā)minor GC;否則會查看是否開啟了分配擔保機制,如果沒有開啟,那么會直接觸發(fā)full GC ,如果開啟了,就會看每次minor GC存活的對象平均大小是否小于等于老年代可用空間大小,如果滿足,則直接minor GC,否則觸發(fā)Full GC。
            在這里插入圖片描述

            4、垃圾收集 ???????4.1、如何判斷一個對象是否存活

            判斷對象是否存活有兩種方式——計數(shù)器算法和可達性分析算法

            ???? 4.1.1、計數(shù)器算法

            ????????此方法比較簡單,每個對象就是專門有個計數(shù)的變量,當該對象被引用一次就會+1;引用失效一次就會-1;當計數(shù)變量為0時,代表該對象沒有被其他對象引用,可以被垃圾回收。
            ????????該方法有個弊端,就是當兩個對象互相引用是,比如A對象引用B對象,B對象又引用A對象,他們之間不可能將計數(shù)器減為0,這就無法將對象進行垃圾回收。

            ??????4.1.2、可達性分析算法

            ???????????將GC roots為起點向下遍歷,遍歷到的對象說明被其他引用,需要存活,沒有遍歷到的對象說明被引用,是垃圾對象,會被回收。
            ???????????GC roots根節(jié)點可以是靜態(tài)變量、局部變量等等
            在這里插入圖片描述

            4.2、垃圾收集算法

            ????垃圾收集算法主要有復制算法、標記清除算法和標記整理算法

            ????4.2.1、復制算法

            ????????效率比較高,主要是年輕代中使用該垃圾算法;它可以將內存分為大小相同的兩塊,每次使用其中的一塊。當這一塊的內存使用完后,就將還存活的對象復制到另一塊去,然后再把使用的空間一次清理掉。這樣就使每次的內存回收都是對內存區(qū)間的一半進行回收。
            ????特點: 效率比較高,但是內存利用率不高;每次只能利用50%的內存
            在這里插入圖片描述

            ????4.2.2、標記清除算法

            ????算法分為“標記”和“清除”階段:標記存活的對象, 統(tǒng)一回收所有未被標記的對象;
            ???? 特點: 1、效率比較低(如果需要標記的對象非常多,那么效率就會下降);2、空間利用率較高,但是會產生空間碎片化,導致大對象在存放時不能存放
            在這里插入圖片描述

            ????4.2.3、標記整理算法

            ???? 根據老年代的特點特出的一種標記算法,標記過程仍然與“標記-清除”算法一樣,但后續(xù)步驟不是直接對可回收對象回收,而是讓所有存活的對象向一端移動,然后直接清理掉端邊界以外的內存。
            在這里插入圖片描述

            4.3、垃圾收集器

            ????常見的垃圾收集器有如下幾種:
            在這里插入圖片描述
            ????如果說收集算法是內存回收的方法論,那么垃圾收集器就是內存回收的具體實現(xiàn)。

            4.3.1、Serial收集器(-XX:+UseSerialGC -XX:+UseSerialOldGC)

            ?????????Serial(串行) 收集器是最基本、歷史最悠久的垃圾收集器了。大家看名字就知道這個收集器是一個單線程收集器了。它 的 “單線程” 的意義不僅僅意味著它只會使用一條垃圾收集線程去完成垃圾收集工作,更重要的是它在進行垃圾收集工作的時候必須暫停其他所有的工作線程( “Stop The World” ),直到它收集結束。
            在這里插入圖片描述
            優(yōu)點:
            它簡單而高效(與其他收集器的單線程相比)。Serial 收集器由于沒有線程交互的開銷,自然可以獲得很高的單線程收集效率。
            Serial Old收集器是Serial收集器的老年代版本,它同樣是一個單線程收集器。它主要有兩大用途:一種用途是在JDK1.5 以及以前的版本中與Parallel Scavenge收集器搭配使用,另一種用途是作為CMS收集器的后備方案 (當CMS在垃圾收集時,垃圾回收的內存遠遠不夠對象創(chuàng)建所使用的內存,那么此時就會觸發(fā)Seral Old收集器做兜底,會STW,整個線程不能使用)。

            4.3.2、Parallel收集器(-XX:+UseParallelGC(年輕代),-XX:+UseParallelOldGC(老年代))

            ?????Parallel收集器其實就是Serial收集器的多線程版本,除了使用多線程進行垃圾收集外,其余行為(控制參數(shù)、收集算法、回收策略等等)和Serial收集器類似。默認的收集線程數(shù)跟cpu核數(shù)相同,當然也可以用參數(shù)(XX:ParallelGCThreads)指定收集線程數(shù),但是一般不推薦修改。 Parallel Scavenge收集器關注點是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的關注點更多的是用戶線程的停頓時間(提高用戶體驗)。所謂吞吐量就是CPU中用于運行用戶代碼的時間與CPU總消耗時間的比值。
            ????? 新生代采用復制算法,老年代采用標記-整理算法。
            在這里插入圖片描述
            ?????Parallel Old收集器是Parallel Scavenge收集器的老年代版本。使用多線程和“標記-整理”算法。在注重吞吐量以及 CPU資源的場合,都可以優(yōu)先考慮 Parallel Scavenge收集器和Parallel Old收集器(JDK8默認的新生代和老年代收集器)。

            4.3.3、ParNew收集器(-XX:+UseParNewGC)

            ?????ParNew收集器其實跟Parallel收集器很類似,區(qū)別主要在于它可以和CMS收集器配合使用。
            ?????新生代采用復制算法,老年代采用標記-整理算法。

            4.3.4、CMS收集器(-XX:+UseConcMarkSweepGC(old))

            ?????CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。它非常符合在注重用戶體驗的應用上使用,它是HotSpot虛擬機第一款真正意義上的并發(fā)收集器,它第一次實現(xiàn)了讓垃圾收集線程與用戶線程 (基本上)同時工作。
            ?????從名字中的Mark Sweep這兩個詞可以看出,CMS收集器是一種 “標記-清除”算法實現(xiàn)。
            過程步驟如下:
            1、初始標記: 暫停所有的其他線程(STW),并記錄下gc roots直接能引用的對象,速度很快。
            2、并發(fā)標記: 并發(fā)標記階段就是從GC Roots的直接關聯(lián)對象開始遍歷整個對象圖的過程, 這個過程耗時較長但是不需要停頓用戶線程, 可以與垃圾收集線程一起并發(fā)運行。因為用戶程序繼續(xù)運行,可能會有導致已經標記過的對象狀態(tài)發(fā)生改變。
            3、重新標記: 重新標記階段就是為了修正并發(fā)標記期間因為用戶程序繼續(xù)運行而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段的時間稍長,遠遠比并發(fā)標記階段時間短。主要用到三色標記里的增量更新算法(見下面詳解)做重新標記。(也是STW)
            4、并發(fā)清理: 開啟用戶線程,同時GC線程開始對未標記的區(qū)域做清掃。這個階段如果有新增對象會被標記為黑色不做任何處理(見下面三色標記算法詳解)。
            5、并發(fā)重置: 重置本次GC過程中的標記數(shù)據。
            在這里插入圖片描述

            從它的名字就可以看出它是一款優(yōu)秀的垃圾收集器,主要優(yōu)點:并發(fā)收集、低停頓。但是它有下面幾個明顯的缺點:
            1、對CPU資源敏感(會和服務搶資源);
            2、無法處理浮動垃圾(在并發(fā)標記和并發(fā)清理階段又產生垃圾,這種浮動垃圾只能等到下一次gc再清理了);
            3、它使用的回收算法-“標記-清除”算法會導致收集結束時會有大量空間碎片產生
            4、執(zhí)行過程中的不確定性,會存在上一次垃圾回收還沒執(zhí)行完,然后垃圾回收又被觸發(fā)的情況,特別是在并發(fā)標記和并發(fā)清理階段會出現(xiàn),一邊回收,系統(tǒng)一邊運行,也許沒回收完就再次觸發(fā)full gc,也就是"concurrent mode failure",此時會進入stop the world,用serial old垃圾收集器來回收。

            4.3.5、G1收集器

            ???G1 (Garbage-First)是一款面向服務器的垃圾收集器,主要針對配備多顆處理器及大容量內存的機器。以極高概率滿足GC 停頓時間要求的同時,還具備高吞吐量性能特征。
            在這里插入圖片描述???G1將Java堆劃分為多個大小相等的獨立區(qū)域(Region),JVM最多可以有2048個Region。 一般Region大小等于堆大小除以2048,比如堆大小為4096M,則Region大小為2M,當然也可以用參數(shù)"XX:G1HeapRegionSize"手動指定Region大小,但是推薦默認的計算方式。
            ???G1保留了年輕代和老年代的概念,但不再是物理隔閡了,它們都是(可以不連續(xù))Region的集合。
            ???默認年輕代對堆內存的占比是5%,如果堆大小為4096M,那么年輕代占據200MB左右的內存,對應大概是100個 Region,可以通過“-XX:G1NewSizePercent”設置新生代初始占比,在系統(tǒng)運行中,JVM會不停的給年輕代增加更多 的Region,但是最多新生代的占比不會超過60%,可以通過“-XX:G1MaxNewSizePercent”調整。年輕代中的Eden和 Survivor對應的region也跟之前一樣,默認8:1:1,假設年輕代現(xiàn)在有1000個region,eden區(qū)對應800個,s0對應100 個,s1對應100個。
            ???一個Region可能之前是年輕代,如果Region進行了垃圾回收,之后可能又會變成老年代,也就是說Region的區(qū)域功能 可能會動態(tài)變化。
            ???G1垃圾收集器對于對象什么時候會轉移到老年代跟之前講過的原則一樣,唯一不同的是對大對象的處理,G1有專門分配 大對象的Region叫Humongous區(qū),而不是讓大對象直接進入老年代的Region中。
            ???在G1中,大對象的判定規(guī)則就是一個大對象超過了一個Region大小的50%,比如按照上面算的,每個Region是2M,只要一個大對象超過了1M,就會被放 入Humongous中,而且一個大對象如果太大,可能會橫跨多個Region來存放。
            ???Full GC的時候除了收集年輕代和老年代之外,也會將Humongous區(qū)一并回收。
            G1收集器一次GC的運作過程大致分為以下幾個步驟:
            1、初始標記(initial mark,STW): 暫停所有的其他線程,并記錄下gc roots直接能引用的對象,速度很快 ;
            2、并發(fā)標記(Concurrent Marking): 同CMS的并發(fā)標記
            3、最終標記(Remark,STW): 同CMS的重新標記
            4、篩選回收(Cleanup,STW): 篩選回收階段首先對各個Region的回收價值和成本進行排序,根據用戶所期望的GC停頓時間(可以用JVM參數(shù) -XX:MaxGCPauseMillis指定)來制定回收計劃,比如說老年代此時有1000個 Region都滿了,但是因為根據預期停頓時間,本次垃圾回收可能只能停頓200毫秒,那么通過之前回收成本計算得知,可能回收其中800個Region剛好需要200ms,那么就只會回收800個Region(Collection Set,要回收的集合),盡量把GC導致的停頓時間控制在我們指定的范圍內。這個階段其實也可以做到與用戶程序一起并發(fā)執(zhí)行,但是因為只回收一部分Region,時間是用戶可控制的,而且停頓用戶線程將大幅提高收集效率。不管是年輕代或是老年代,回收算法主要用的是復制算法,將一個region中的存活對象復制到另一個region中,這種不會像CMS那樣 回收完因為有很多內存碎片還需要整理一次,G1采用復制算法回收幾乎不會有太多內存碎片。(注意:CMS回收階段是跟用戶線程一起并發(fā)執(zhí)行的,G1因為內部實現(xiàn)太復雜暫時沒實現(xiàn)并發(fā)回收,不過到了Shenandoah就實現(xiàn)了并發(fā)收集,Shenandoah可以看成是G1的升級版本)。
            在這里插入圖片描述G1收集器在后臺維護了一個優(yōu)先列表,每次根據允許的收集時間,優(yōu)先選擇回收價值大的Region(這也就是它的名字 Garbage-First的由來),比如一個Region花200ms能回收10M垃圾,另外一個Region花50ms能回收20M垃圾,在回收時間有限情況下,G1當然會優(yōu)先選擇后面這個Region回收。這種使用Region劃分內存空間以及有優(yōu)先級的區(qū)域回收方式,保證了G1收集器在有限時間內可以盡可能高的收集效率。
            G1垃圾收集分類:
            ???1、YoungGC:
            ???????YoungGC并不是說現(xiàn)有的Eden區(qū)放滿了就會馬上觸發(fā),G1會計算下現(xiàn)在Eden區(qū)回收大概要多久時間,如果回收時間遠遠小于參數(shù) -XX:MaxGCPauseMills 設定的值,那么增加年輕代的region,繼續(xù)給新對象存放,不會馬上做Young GC,直到下一次Eden區(qū)放滿,G1計算回收時間接近參數(shù) -XX:MaxGCPauseMills 設定的值,那么就會觸發(fā)Young GC。
            ???2、MixedGC:
            ???????不是FullGC,老年代的堆占有率達到參數(shù)(-XX:InitiatingHeapOccupancyPercent)設定的值則觸發(fā),回收所有的Young和部分Old(根據期望的GC停頓時間確定old區(qū)垃圾收集的優(yōu)先順序)以及大對象區(qū),正常情況G1的垃圾收集是先做MixedGC,主要使用復制算法,需要把各個region中存活的對象拷貝到別的region里去,拷貝過程中如果發(fā)現(xiàn)沒有足夠的空region能夠承載拷貝對象就會觸發(fā)一次Full GC。
            ???3、Full GC:
            ???????停止系統(tǒng)程序,然后采用單線程進行標記、清理和壓縮整理,好空閑出來一批Region來供下一次MixedGC使用,這 個過程是非常耗時的。(Shenandoah優(yōu)化成多線程收集了)

            4.4、垃圾收集底層算法 ???????????4.4.1、三色標記

            ????在并發(fā)標記的過程中,因為標記期間應用線程還在繼續(xù)跑,對象間的引用可能發(fā)生變化,多標和漏標的情況就有可能發(fā)生。
            ????這里我們引入“三色標記”來給大家解釋下,把Gc roots可達性分析遍歷對象過程中遇到的對象, 按照“是否訪問過”這個條件標記成以下三種顏色:

            • 黑色: 表示對象已經被垃圾收集器訪問過, 且這個對象的所有引用都已經掃描過。 黑色的對象代表已經掃描過, 它是安全存活的, 如果有其他對象引用指向了黑色對象,無須重新掃描一遍。 黑色對象不可能直接(不經過灰色對象) 指向某個白色對象。
            • 灰色: 表示對象已經被垃圾收集器訪問過, 但這個對象上至少存在一個引用還沒有被掃描過。
            • 白色: 表示對象尚未被垃圾收集器訪問過。 顯然在可達性分析剛剛開始的階段, 所有的對象都是白色的, 若 在分析結束的階段, 仍然是白色的對象, 即代表不可達。
              在這里插入圖片描述
            4.5、一次完整GC流程

            ???這里準備用大白話來給大家來講解哈。首先對象創(chuàng)建之后,會存放進堆中新生代的Eden區(qū)中,當Eden區(qū)滿了,會觸發(fā)minoe GC,存活的對象移動到S0區(qū),并且存活的對象GC年齡+1;此時又有新建的對象存放進Eden區(qū),當Eden區(qū)滿了,就又會觸發(fā)minior GC,這次不單單回收Eden區(qū),還會回收S區(qū),此時存活的對象會移動到S1區(qū),存活的對象年齡+1;反反復復這樣垃圾回收,當對象GC年齡大于15次時,那么此時對象會存放進老年代;當老年代滿了之后,會觸發(fā)Full GC,F(xiàn)ull GC不單單回收老年代,它還回收新生代,F(xiàn)ull GC 的時間會比較長,大概是Minor GC的十倍左右。
            ???好了,上面就是一次完整的GC流程,大白話講解的應該還算比較清晰。不理解的可以在評論中評論哦。

            5、JVM調優(yōu)

            ???這個JVM調優(yōu)就先不給大家講解了吧,因為今天是年前上班的最后一天,已經下班了,我還明天中午的高鐵,今天晚上回去還要收拾東西;今天就不講解了,等有時間了給大家補上哈。
            ???現(xiàn)在在回家的高鐵上,時間是2023年01月19日11:43:39,那今天作為程序員的我來裝下逼,當然不是敲代碼哈,是來裝逼完成昨天的諾言,來兌現(xiàn)昨天說的JVM調優(yōu)這一章節(jié),廢話少說,來開始我們的寫作。
            ???談起JVM調優(yōu),主要的就是將其GC頻率降低和減少每次GC的時間,主要是Full GC,當然Minor GC也是要調的,為什么是主要呢,因為Full GC時間比較長,一般是其Minor GC的十倍左右。
            ???調優(yōu)的主要目的是: 降低到合理的Minor GC和Full GC的頻率以及調優(yōu)到我們能夠接受的GC所用時間范圍,下面我先圍繞下面幾個大的方向來說其調優(yōu)。
            ???1、Minor GC方面:
            ???????a: 在高壓力情況下,對象創(chuàng)建的非常頻繁,那么觸發(fā)Minor GC就比較頻繁,可能有些對象根本不是大對象,但是由于頻繁觸發(fā)Minor GC,那么年齡已經到達了15次,那么此時就會存放到老年代中,占用老年代空間就會頻繁觸發(fā)Full GC,那么這種會影響其系統(tǒng)正常使用;這種情況可以調大新生代內存空間大小,但是調大可能內存空間大小會增加Minor GC時間,這種帶來的GC時間延長也要能接受哈;注意: 剛剛我說的是可能增加,為什么可能增加呢,是因為新生代采用的復制算法,它的過程是先標記,然后再復制,在這兩步中,標記比較耗時間,復制是比較快的;但是對象存活時間比較短,可能在標記階段就已經是垃圾對象了,雖然的新生代空間大了,但是當觸發(fā)Minor GC時,已經有很多對象死亡了,無需標記,因此我在上面說可能Minor GC的時間增大,但是不一定增大。
            ???????b: 當觸發(fā)Minor GC時,存活的對象內存可能會大于S區(qū)內存,那么此時就會直接將對象存放進老年代中,這種其實是非常可怕的,因為真實該對象的GC年齡才1歲,就直接存放進大對象中,那么Full GC會非常頻繁的。這種可以調整其Eden區(qū)和S區(qū)比例,增加其S區(qū)大小。
            ???????c: 還有種情況就是對象的動態(tài)年齡判斷機制,當對象的某一年齡的內存大小大于S區(qū)的50%,那么就會將大于等于該年齡的對象都移至老年代中,這種也會頻繁觸發(fā)Full GC,同樣解決方法是增大S區(qū)大小。

            ???2、大對象方面: 大對象方面其實比較好理解,上面我已經提到了當對象大于我們設置的-XX: PretenureSizeThreshold參數(shù)的大小時,則會認為是大對象,會直接將對象存放進老年代中,那么老年代的內存空間將會很快沾滿,觸發(fā)Full GC,F(xiàn)ull GC的頻率會非常頻繁;其實這可以有兩種解決方法:
            ???????a: 第一種方法就是調高-XX: PretenureSizeThreshold的參數(shù)大小,使認為不是大對象,不直接存放進老年代中,減少Full GC的頻率,提高用戶的體驗度,但是調大其-XX: PretenureSizeThreshold的參數(shù)大小后,要注意S區(qū)的大小,如果S區(qū)的內存不足以存放,又觸發(fā)了上述的動態(tài)年齡判斷和大于S區(qū)內存的50%,又給直接存放進了老年代,那么這種情況是不行的,因此也要注意下這種問題。
            ???????b: 我們也可以編寫個腳本,在系統(tǒng)不忙的情況下運行該腳本去進行Full GC;這種情況是不提倡的哈,盡量還是采用上面的a方法。
            ???3、內存泄漏引起的頻繁Minor GC和Full GC: 最終會引發(fā)OOM,因此在編寫代碼的時候一定要注意。
            ???4、純代碼方面: 這里可能是某些for循環(huán)創(chuàng)建大量對象和使用了不當?shù)臄?shù)據結構能問題引起的頻繁GC,針對這種情況就建議查看代碼來進行解決了。
            ???好了上面就是大致的調優(yōu)方面的建議,具體的調優(yōu)過程就不給大家分享了,這方面的調優(yōu)只能實戰(zhàn)才能悟出來真理,我如果直接給你講解的話也不太好,還希望大家實戰(zhàn)吧。
            ???好了經過四十分鐘在高鐵上的寫終于寫完了,也裝逼完了,好了,今天2023年01月19日12:25:38這篇文章暫時 分享到這吧,等后期有需要補充的再補充。——于G8270高鐵

            ???
            ???廢話少說,趕緊來個結尾,準備收拾東西下班回家過年!
            ???再次提前祝大家新年快樂哦(從下寫作文老師就教導我們寫作文要首尾相應🐶)
            ???文章中有講解不對的內容希望大家在評論區(qū)中指出哦,希望大家點贊評論轉發(fā)哦,點贊超過三個我就更新下一篇——MySQL系列

            你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧

            新聞標題:2023跳槽最新面試題整理——JVM系列-創(chuàng)新互聯(lián)
            鏈接URL:http://www.jbt999.com/article16/ccdidg.html

            成都網站建設公司_創(chuàng)新互聯(lián),為您提供做網站小程序開發(fā)標簽優(yōu)化、移動網站建設、企業(yè)網站制作、靜態(tài)網站

            廣告

            聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:[email protected]。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

            搜索引擎優(yōu)化

              <del id="d4fwx"><form id="d4fwx"></form></del>
              <del id="d4fwx"><form id="d4fwx"></form></del><del id="d4fwx"><form id="d4fwx"></form></del>

                    <code id="d4fwx"><abbr id="d4fwx"></abbr></code>
                  • 国产成人在线观看免费网站 | 爱爱爱爱爱视频 | 黄色毛片毛片 | 久久无码成人电影 | 猫咪亚洲AV成人无码电影 |