www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]這是面試專題系列第五篇JVM篇。這一篇可能稍微比較長,沒有耐心的同學(xué)建議直接拖到最后。

這是面試專題系列第五篇JVM篇。這一篇可能稍微比較長,沒有耐心的同學(xué)建議直接拖到最后。

說說JVM的內(nèi)存布局?

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

Java虛擬機主要包含幾個區(qū)域:

:堆Java虛擬機中最大的一塊內(nèi)存,是線程共享的內(nèi)存區(qū)域,基本上所有的對象實例數(shù)組都是在堆上分配空間。堆區(qū)細(xì)分為Yound區(qū)年輕代和Old區(qū)老年代,其中年輕代又分為Eden、S0、S1 3個部分,他們默認(rèn)的比例是8:1:1的大小。

:棧是線程私有的內(nèi)存區(qū)域,每個方法執(zhí)行的時候都會在棧創(chuàng)建一個棧幀,方法的調(diào)用過程就對應(yīng)著棧的入棧和出棧的過程。每個棧幀的結(jié)構(gòu)又包含局部變量表、操作數(shù)棧、動態(tài)連接、方法返回地址。

局部變量表用于存儲方法參數(shù)和局部變量。當(dāng)?shù)谝粋€方法被調(diào)用的時候,他的參數(shù)會被傳遞至從0開始的連續(xù)的局部變量表中。

操作數(shù)棧用于一些字節(jié)碼指令從局部變量表中傳遞至操作數(shù)棧,也用來準(zhǔn)備方法調(diào)用的參數(shù)以及接收方法返回結(jié)果。

動態(tài)連接用于將符號引用表示的方法轉(zhuǎn)換為實際方法的直接引用。

元數(shù)據(jù):在Java1.7之前,包含方法區(qū)的概念,常量池就存在于方法區(qū)(永久代)中,而方法區(qū)本身是一個邏輯上的概念,在1.7之后則是把常量池移到了堆內(nèi),1.8之后移出了永久代的概念(方法區(qū)的概念仍然保留),實現(xiàn)方式則是現(xiàn)在的元數(shù)據(jù)。它包含類的元信息和運行時常量池。

Class文件就是類和接口的定義信息。

運行時常量池就是類和接口的常量池運行時的表現(xiàn)形式。

本地方法棧:主要用于執(zhí)行本地native方法的區(qū)域

程序計數(shù)器:也是線程私有的區(qū)域,用于記錄當(dāng)前線程下虛擬機正在執(zhí)行的字節(jié)碼的指令地址

知道new一個對象的過程嗎?

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

當(dāng)虛擬機遇見new關(guān)鍵字時候,實現(xiàn)判斷當(dāng)前類是否已經(jīng)加載,如果類沒有加載,首先執(zhí)行類的加載機制,加載完成后再為對象分配空間、初始化等。

  1. 首先校驗當(dāng)前類是否被加載,如果沒有加載,執(zhí)行類加載機制
  2. 加載:就是從字節(jié)碼加載成二進(jìn)制流的過程
  3. 驗證:當(dāng)然加載完成之后,當(dāng)然需要校驗Class文件是否符合虛擬機規(guī)范,跟我們接口請求一樣,第一件事情當(dāng)然是先做個參數(shù)校驗了
  4. 準(zhǔn)備:為靜態(tài)變量、常量賦默認(rèn)值
  5. 解析:把常量池中符號引用(以符號描述引用的目標(biāo))替換為直接引用(指向目標(biāo)的指針或者句柄等)的過程
  6. 初始化:執(zhí)行static代碼塊(cinit)進(jìn)行初始化,如果存在父類,先對父類進(jìn)行初始化

Ps:靜態(tài)代碼塊是絕對線程安全的,只能隱式被java虛擬機在類加載過程中初始化調(diào)用!(此處該有問題static代碼塊線程安全嗎?)

當(dāng)類加載完成之后,緊接著就是對象分配內(nèi)存空間和初始化的過程

  1. 首先為對象分配合適大小的內(nèi)存空間
  2. 接著為實例變量賦默認(rèn)值
  3. 設(shè)置對象的頭信息,對象hash碼、GC分代年齡、元數(shù)據(jù)信息等
  4. 執(zhí)行構(gòu)造函數(shù)(init)初始化

知道雙親委派模型嗎?

類加載器自頂向下分為:

  1. Bootstrap ClassLoader啟動類加載器:默認(rèn)會去加載JAVA_HOME/lib目錄下的jar
  2. Extention ClassLoader擴展類加載器:默認(rèn)去加載JAVA_HOME/lib/ext目錄下的jar
  3. Application ClassLoader應(yīng)用程序類加載器:比如我們的web應(yīng)用,會加載web程序中ClassPath下的類
  4. User ClassLoader用戶自定義類加載器:由用戶自己定義

當(dāng)我們在加載類的時候,首先都會向上詢問自己的父加載器是否已經(jīng)加載,如果沒有則依次向上詢問,如果沒有加載,則從上到下依次嘗試是否能加載當(dāng)前類,直到加載成功。

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

說說有哪些垃圾回收算法?

標(biāo)記-清除

統(tǒng)一標(biāo)記出需要回收的對象,標(biāo)記完成之后統(tǒng)一回收所有被標(biāo)記的對象,而由于標(biāo)記的過程需要遍歷所有的GC ROOT,清除的過程也要遍歷堆中所有的對象,所以標(biāo)記-清除算法的效率低下,同時也帶來了內(nèi)存碎片的問題。

復(fù)制算法

為了解決性能的問題,復(fù)制算法應(yīng)運而生,它將內(nèi)存分為大小相等的兩塊區(qū)域,每次使用其中的一塊,當(dāng)一塊內(nèi)存使用完之后,將還存活的對象拷貝到另外一塊內(nèi)存區(qū)域中,然后把當(dāng)前內(nèi)存清空,這樣性能和內(nèi)存碎片的問題得以解決。但是同時帶來了另外一個問題,可使用的內(nèi)存空間縮小了一半!

因此,誕生了我們現(xiàn)在的常見的年輕代+老年代的內(nèi)存結(jié)構(gòu):Eden+S0+S1組成,因為根據(jù)IBM的研究顯示,98%的對象都是朝生夕死,所以實際上存活的對象并不是很多,完全不需要用到一半內(nèi)存浪費,所以默認(rèn)的比例是8:1:1。

這樣,在使用的時候只使用Eden區(qū)和S0S1中的一個,每次都把存活的對象拷貝另外一個未使用的Survivor區(qū),同時清空Eden和使用的Survivor,這樣下來內(nèi)存的浪費就只有10%了。

如果最后未使用的Survivor放不下存活的對象,這些對象就進(jìn)入Old老年代了。

PS:所以有一些初級點的問題會問你為什么要分為Eden區(qū)和2個Survior區(qū)?有什么作用?就是為了節(jié)省內(nèi)存和解決內(nèi)存碎片的問題,這些算法都是為了解決問題而產(chǎn)生的,如果理解原因你就不需要死記硬背了

標(biāo)記-整理

針對老年代再用復(fù)制算法顯然不合適,因為進(jìn)入老年代的對象都存活率比較高了,這時候再頻繁的復(fù)制對性能影響就比較大,而且也不會再有另外的空間進(jìn)行兜底。所以針對老年代的特點,通過標(biāo)記-整理算法,標(biāo)記出所有的存活對象,讓所有存活的對象都向一端移動,然后清理掉邊界以外的內(nèi)存空間。

那么什么是GC ROOT?有哪些GC ROOT?

上面提到的標(biāo)記的算法,怎么標(biāo)記一個對象是否存活?簡單的通過引用計數(shù)法,給對象設(shè)置一個引用計數(shù)器,每當(dāng)有一個地方引用他,就給計數(shù)器+1,反之則計數(shù)器-1,但是這個簡單的算法無法解決循環(huán)引用的問題。

Java通過可達(dá)性分析算法來達(dá)到標(biāo)記存活對象的目的,定義一系列的GC ROOT為起點,從起點開始向下開始搜索,搜索走過的路徑稱為引用鏈,當(dāng)一個對象到GC ROOT沒有任何引用鏈相連的話,則對象可以判定是可以被回收的。

而可以作為GC ROOT的對象包括:

  1. 棧中引用的對象

  2. 靜態(tài)變量、常量引用的對象

  3. 本地方法棧native方法引用的對象

垃圾回收器了解嗎?年輕代和老年代都有哪些垃圾回收器?

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

年輕代的垃圾收集器包含有Serial、ParNew、Parallell,老年代則包括Serial Old老年代版本、CMS、Parallel Old老年代版本和JDK11中的船新的G1收集器。

Serial:單線程版本收集器,進(jìn)行垃圾回收的時候會STW(Stop The World),也就是進(jìn)行垃圾回收的時候其他的工作線程都必須暫停

ParNew:Serial的多線程版本,用于和CMS配合使用

Parallel Scavenge:可以并行收集的多線程垃圾收集器

Serial Old:Serial的老年代版本,也是單線程

Parallel Old:Parallel Scavenge的老年代版本

CMS(Concurrent Mark Sweep):CMS收集器是以獲取最短停頓時間為目標(biāo)的收集器,相對于其他的收集器STW的時間更短暫,可以并行收集是他的特點,同時他基于標(biāo)記-清除算法,整個GC的過程分為4步。

  1. 初始標(biāo)記:標(biāo)記GC ROOT能關(guān)聯(lián)到的對象,需要STW
  2. 并發(fā)標(biāo)記:從GCRoots的直接關(guān)聯(lián)對象開始遍歷整個對象圖的過程,不需要STW
  3. 重新標(biāo)記:為了修正并發(fā)標(biāo)記期間,因用戶程序繼續(xù)運作而導(dǎo)致標(biāo)記產(chǎn)生改變的標(biāo)記,需要STW
  4. 并發(fā)清除:清理刪除掉標(biāo)記階段判斷的已經(jīng)死亡的對象,不需要STW

從整個過程來看,并發(fā)標(biāo)記和并發(fā)清除的耗時最長,但是不需要停止用戶線程,而初始標(biāo)記和重新標(biāo)記的耗時較短,但是需要停止用戶線程,總體而言,整個過程造成的停頓時間較短,大部分時候是可以和用戶線程一起工作的。

G1(Garbage First):G1收集器是JDK9的默認(rèn)垃圾收集器,而且不再區(qū)分年輕代和老年代進(jìn)行回收。

G1的原理了解嗎?

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

G1作為JDK9之后的服務(wù)端默認(rèn)收集器,且不再區(qū)分年輕代和老年代進(jìn)行垃圾回收,他把內(nèi)存劃分為多個Region,每個Region的大小可以通過-XX:G1HeapRegionSize設(shè)置,大小為1~32M,對于大對象的存儲則衍生出Humongous的概念,超過Region大小一半的對象會被認(rèn)為是大對象,而超過整個Region大小的對象被認(rèn)為是超級大對象,將會被存儲在連續(xù)的N個Humongous Region中,G1在進(jìn)行回收的時候會在后臺維護(hù)一個優(yōu)先級列表,每次根據(jù)用戶設(shè)定允許的收集停頓時間優(yōu)先回收收益最大的Region。

G1的回收過程分為以下四個步驟:

  1. 初始標(biāo)記:標(biāo)記GC ROOT能關(guān)聯(lián)到的對象,需要STW
  2. 并發(fā)標(biāo)記:從GCRoots的直接關(guān)聯(lián)對象開始遍歷整個對象圖的過程,掃描完成后還會重新處理并發(fā)標(biāo)記過程中產(chǎn)生變動的對象
  3. 最終標(biāo)記:短暫暫停用戶線程,再處理一次,需要STW
  4. 篩選回收:更新Region的統(tǒng)計數(shù)據(jù),對每個Region的回收價值和成本排序,根據(jù)用戶設(shè)置的停頓時間制定回收計劃。再把需要回收的Region中存活對象復(fù)制到空的Region,同時清理舊的Region。需要STW

總的來說除了并發(fā)標(biāo)記之外,其他幾個過程也還是需要短暫的STW,G1的目標(biāo)是在停頓和延遲可控的情況下盡可能提高吞吐量。

什么時候會觸發(fā)YGC和FGC?對象什么時候會進(jìn)入老年代?

當(dāng)一個新的對象來申請內(nèi)存空間的時候,如果Eden區(qū)無法滿足內(nèi)存分配需求,則觸發(fā)YGC,使用中的Survivor區(qū)和Eden區(qū)存活對象送到未使用的Survivor區(qū),如果YGC之后還是沒有足夠空間,則直接進(jìn)入老年代分配,如果老年代也無法分配空間,觸發(fā)FGC,F(xiàn)GC之后還是放不下則報出OOM異常。

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

YGC之后,存活的對象將會被復(fù)制到未使用的Survivor區(qū),如果S區(qū)放不下,則直接晉升至老年代。而對于那些一直在Survivor區(qū)來回復(fù)制的對象,通過-XX:MaxTenuringThreshold配置交換閾值,默認(rèn)15次,如果超過次數(shù)同樣進(jìn)入老年代。

此外,還有一種動態(tài)年齡的判斷機制,不需要等到MaxTenuringThreshold就能晉升老年代。如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進(jìn)入老年代。

頻繁FullGC怎么排查?

這種問題最好的辦法就是結(jié)合有具體的例子舉例分析,如果沒有就說一般的分析步驟。發(fā)生FGC有可能是內(nèi)存分配不合理,比如Eden區(qū)太小,導(dǎo)致對象頻繁進(jìn)入老年代,這時候通過啟動參數(shù)配置就能看出來,另外有可能就是存在內(nèi)存泄露,可以通過以下的步驟進(jìn)行排查:

  1. jstat -gcutil或者查看gc.log日志,查看內(nèi)存回收情況
《我想進(jìn)大廠》之JVM奪命連環(huán)10問

S0 S1 分別代表兩個Survivor區(qū)占比

E代表Eden區(qū)占比,圖中可以看到使用78%

O代表老年代,M代表元空間,YGC發(fā)生54次,YGCT代表YGC累計耗時,GCT代表GC累計耗時。

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

[GC [FGC 開頭代表垃圾回收的類型

PSYoungGen: 6130K->6130K(9216K)] 12274K->14330K(19456K), 0.0034895 secs代表YGC前后內(nèi)存使用情況

Times: user=0.02 sys=0.00, real=0.00 secs,user表示用戶態(tài)消耗的CPU時間,sys表示內(nèi)核態(tài)消耗的CPU時間,real表示各種墻時鐘的等待時間

這兩張圖只是舉例并沒有關(guān)聯(lián)關(guān)系,比如你從圖里面看能到是否進(jìn)行FGC,F(xiàn)GC的時間花費多長,GC后老年代,年輕代內(nèi)存是否有減少,得到一些初步的情況來做出判斷。

  1. dump出內(nèi)存文件在具體分析,比如通過jmap命令jmap -dump:format=b,file=dumpfile pid,導(dǎo)出之后再通過 Eclipse Memory Analyzer等工具進(jìn)行分析,定位到代碼,修復(fù)

這里還會可能存在一個提問的點,比如CPU飆高,同時FGC怎么辦?辦法比較類似

  1. 找到當(dāng)前進(jìn)程的pid,top -p pid -H 查看資源占用,找到線程
  2. printf “%x\n” pid,把線程pid轉(zhuǎn)為16進(jìn)制,比如0x32d
  3. jstack pid|grep -A 10 0x32d查看線程的堆棧日志,還找不到問題繼續(xù)
  4. dump出內(nèi)存文件用MAT等工具進(jìn)行分析,定位到代碼,修復(fù)

JVM調(diào)優(yōu)有什么經(jīng)驗嗎?

要明白一點,所有的調(diào)優(yōu)的目的都是為了用更小的硬件成本達(dá)到更高的吞吐,JVM的調(diào)優(yōu)也是一樣,通過對垃圾收集器和內(nèi)存分配的調(diào)優(yōu)達(dá)到性能的最佳。

簡單的參數(shù)含義

首先,需要知道幾個主要的參數(shù)含義。

《我想進(jìn)大廠》之JVM奪命連環(huán)10問
  1. -Xms設(shè)置初始堆的大小,-Xmx設(shè)置最大堆的大小
  2. -XX:NewSize年輕代大小,-XX:MaxNewSize年輕代最大值,-Xmn則是相當(dāng)于同時配置-XX:NewSize和-XX:MaxNewSize為一樣的值
  3. -XX:NewRatio設(shè)置年輕代和年老代的比值,如果為3,表示年輕代與老年代比值為1:3,默認(rèn)值為2
  4. -XX:SurvivorRatio年輕代和兩個Survivor的比值,默認(rèn)8,代表比值為8:1:1
  5. -XX:PretenureSizeThreshold 當(dāng)創(chuàng)建的對象超過指定大小時,直接把對象分配在老年代。
  6. -XX:MaxTenuringThreshold設(shè)定對象在Survivor復(fù)制的最大年齡閾值,超過閾值轉(zhuǎn)移到老年代
  7. -XX:MaxDirectMemorySize當(dāng)Direct ByteBuffer分配的堆外內(nèi)存到達(dá)指定大小后,即觸發(fā)Full GC

調(diào)優(yōu)

  1. 為了打印日志方便排查問題最好開啟GC日志,開啟GC日志對性能影響微乎其微,但是能幫助我們快速排查定位問題。-XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:gc.log
  2. 一般設(shè)置-Xms=-Xmx,這樣可以獲得固定大小的堆內(nèi)存,減少GC的次數(shù)和耗時,可以使得堆相對穩(wěn)定
  3. -XX:+HeapDumpOnOutOfMemoryError讓JVM在發(fā)生內(nèi)存溢出的時候自動生成內(nèi)存快照,方便排查問題
  4. -Xmn設(shè)置新生代的大小,太小會增加YGC,太大會減小老年代大小,一般設(shè)置為整個堆的1/4到1/3
  5. 設(shè)置-XX:+DisableExplicitGC禁止系統(tǒng)System.gc(),防止手動誤觸發(fā)FGC造成問題

特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

長按訂閱更多精彩▼

《我想進(jìn)大廠》之JVM奪命連環(huán)10問

如有收獲,點個在看,誠摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉