JVM 內(nèi)存模型面試總結(jié)

1. 什么是JVM?

就是 JAVA 虛擬機(jī), 它只識別 .class 類型文件,它能夠?qū)?class 文件中的字節(jié)碼指令進(jìn)行識別并調(diào)用操作系統(tǒng)向上的 API 完成動作。

2. Java 代碼的運(yùn)行過程?

Java 源代碼 -> 編輯器 -> 字節(jié)碼文件

字節(jié)碼 -> JVM -> 機(jī)器碼文件

每一種平臺的解釋器是不同的,但是實(shí)現(xiàn)的虛擬機(jī)是相同的,這也就是 Java 為什么能夠
跨平臺的原因

3. JVM后臺常駐線程有?

  1. 虛擬機(jī)線程
  2. 周期任務(wù)線程
  3. Gc 線程
  4. 編輯器線程
  5. 信號分發(fā)線程

4. JVM內(nèi)存區(qū)域分為?

  1. 私有區(qū)域 ,包括程序計(jì)數(shù)器,虛擬機(jī)棧,本地方法區(qū)
  2. 線程共享區(qū),包括Java堆,方法區(qū)
  3. 直接內(nèi)存

線程私有數(shù)據(jù)區(qū)域生命周期與線程相同, 依賴用戶線程的啟動/結(jié)束 而 創(chuàng)建/銷毀(在 Hotspot
VM 內(nèi)

線程共享區(qū)域隨虛擬機(jī)的啟動/關(guān)閉而創(chuàng)建/銷毀

運(yùn)行時(shí)常量池(Runtime Constant Pool)是方法區(qū)的一部分。

5. 介紹下JAVA 虛擬機(jī)棧?

Java虛擬機(jī)棧是描述Java方法運(yùn)行過程的內(nèi)存模型。
Java虛擬機(jī)棧會為每一個(gè)即將運(yùn)行的方法分配“棧幀”空間,用于保存改方法運(yùn)行過程中所需要的一些信息,例如局部變量、操作數(shù)棧、動態(tài)鏈接、方法出口信息等。

Java虛擬機(jī)棧是由一個(gè)個(gè)棧幀組成,而每個(gè)棧幀中都擁有:局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口信息。

局部變量表的創(chuàng)建是在方法被執(zhí)行的時(shí)候,隨著棧幀的創(chuàng)建而創(chuàng)建。而且,局部變量表的大小在編譯時(shí)期就確定下來了,在創(chuàng)建的時(shí)候只需分配事先規(guī)定好的大小即可。

Java虛擬機(jī)棧會出現(xiàn)兩種異常:
StackOverFlowError
OutOfMemoryError

StackOverFlowError:當(dāng)線程請求棧的深度超過當(dāng)前Java虛擬機(jī)棧的最大深度的時(shí)候,就拋出StackOverFlowError異常。

OutOfMemoryError:
若Java虛擬機(jī)棧的內(nèi)存大小允許動態(tài)擴(kuò)展,且當(dāng)線程請求棧時(shí)內(nèi)存用完了,無法再動態(tài)擴(kuò)展了,此時(shí)拋出OutOfMemoryError異常。

6. 介紹下JAVA 堆?

線程共享 :整個(gè)Java虛擬機(jī)只有一個(gè)堆,所有的線程都訪問同一個(gè)堆。

在虛擬機(jī)啟動時(shí)創(chuàng)建。
垃圾回收的主要場所。
不同的區(qū)域存放具有不同生命周期的對象。這樣可以根據(jù)不同的區(qū)域使用不同的垃圾回收算法,從而更具有針對性,從而更高效。
堆的大小既可以固定也可以擴(kuò)展,但主流的虛擬機(jī)堆的大小是可擴(kuò)展的,因此當(dāng)線程請求分配內(nèi)存,但堆已滿,且內(nèi)存已滿無法再擴(kuò)展時(shí),就拋出OutOfMemoryError。

7. 介紹下JAVA 方法區(qū)?

方法區(qū)中存放已經(jīng)被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等。

方法區(qū)是堆的一個(gè)邏輯部分,因此和堆一樣,都是線程共享的。整個(gè)虛擬機(jī)中只有一個(gè)方法區(qū)。

方法區(qū)中的信息一般需要長期存在,而且它又是堆的邏輯分區(qū),因此用堆的劃分方法,我們把方法區(qū)稱為老年代。

對方法區(qū)的內(nèi)存回收的主要目標(biāo)是:對常量池的回收 和 對類型的卸載。長期存在。

方法區(qū)中存放數(shù)據(jù):類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼。其中常量存儲在運(yùn)行時(shí)常量池中。

常量池存在于方法區(qū)。

8. 從GC的角度,JAVA堆還可以怎么分?JVM運(yùn)行時(shí)內(nèi)存

  1. 新生代,包括Edan 區(qū),F(xiàn)rom Survivor 和 To Survivior
  2. 老年代
  3. 永久代

9. 介紹一下新生代

  1. Edan區(qū) :Java新對象的出生地(如果新創(chuàng)建的對象占用內(nèi)存很大,則直接分配到老
    年代)。當(dāng) Eden區(qū)內(nèi)存不夠的時(shí)候就會觸發(fā) MinorGC,對新生代區(qū)進(jìn)行
    一次垃圾回收。

  2. Survivor From : 上一次 GC 的幸存者,作為這一次 GC 的被掃描者.

  3. Survivor To : 保留了一次 MinorGC 過程中的幸存者.

10. MinorGC 的過程?

復(fù)制 , 清空, 互換

MinorGC 采用復(fù)制算法。

1: eden、 servicorFrom 復(fù)制到 ServicorTo,年齡+1

首先,把 Eden 和 ServivorFrom 區(qū)域中存活的對象復(fù)制到 ServicorTo 區(qū)域(如果有對象的年
齡以及達(dá)到了老年的標(biāo)準(zhǔn),則賦值到老年代區(qū)),同時(shí)把這些對象的年齡+1(如果 ServicorTo 不
夠位置了就放到老年區(qū));

2: 清空 eden、 servicorFrom

然后,清空 Eden 和 ServicorFrom 中的對象;

3: ServicorTo 和 ServicorFrom 互換

最后, ServicorTo 和 ServicorFrom 互換,原 ServicorTo 成為下一次 GC 時(shí)的 ServicorFrom
區(qū)。

11. 介紹下老年代和老年代的MajorGC?

老年代的對象比較穩(wěn)定,所以 MajorGC 不會頻繁執(zhí)行。在進(jìn)行 MajorGC 前一般都先進(jìn)行
了一次 MinorGC,使得有新生代的對象晉身入老年代,導(dǎo)致空間不夠用時(shí)才觸發(fā)。

MajorGC 采用標(biāo)記清除算法:首先掃描一次所有老年代,標(biāo)記出存活的對象,然后回收沒
有標(biāo)記的對象。 MajorGC 的耗時(shí)比較長,因?yàn)橐獟呙柙倩厥铡?MajorGC 會產(chǎn)生內(nèi)存碎片,為了減
少內(nèi)存損耗,我們一般需要進(jìn)行合并或者標(biāo)記出來方便下次直接分配。當(dāng)老年代也滿了裝不下的
時(shí)候,就會拋出 OOM(Out of Memory)異常。

12. 介紹下永久代?

主要存放 Class 和 Meta(元數(shù)據(jù))的信息,Class 在被加載的時(shí)候被
放入永久區(qū)域, 它和和存放實(shí)例的區(qū)域不同,GC 不會在主程序運(yùn)行期對永久區(qū)域進(jìn)行清理。所以這
也導(dǎo)致了永久代的區(qū)域會隨著加載的 Class 的增多而脹滿,最終拋出 OOM 異常。

當(dāng)對象在 Survivor 區(qū)躲過一次 GC 后,其年齡就會+1。 默認(rèn)情況下年齡到達(dá) 15 的對象會被
移到老生代中。

13. JAVA8 將永久代替換為元數(shù)據(jù)區(qū)

Java8 中, 永久代已經(jīng)被移除,被一個(gè)稱為“元數(shù)據(jù)區(qū)”(元空間)的區(qū)域所取代。元空間
的本質(zhì)和永久代類似,

元空間與永久代之間最大的區(qū)別在于: 元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。

因此,默認(rèn)情況下,元空間的大小僅受本地內(nèi)存限制。

14. GC 如何確定是垃圾?

  1. 引用計(jì)數(shù)法

在 Java 中,引用和對象是有關(guān)聯(lián)的。如果要操作對象則必須用引用進(jìn)行。因此,很顯然一個(gè)簡單
的辦法是通過引用計(jì)數(shù)來判斷一個(gè)對象是否可以回收。簡單說,即一個(gè)對象如果沒有任何與之關(guān)
聯(lián)的引用, 即他們的引用計(jì)數(shù)都不為 0, 則說明對象不太可能再被用到,那么這個(gè)對象就是可回收
對象。

  1. 可達(dá)性分析

為了解決引用計(jì)數(shù)法的循環(huán)引用問題, Java 使用了可達(dá)性分析的方法。通過一系列的“GC roots”
對象作為起點(diǎn)搜索。如果在“GC roots”和一個(gè)對象之間沒有可達(dá)路徑,則稱該對象是不可達(dá)的

不可達(dá)對象不等價(jià)于可回收對象, 不可達(dá)對象變?yōu)榭苫厥諏ο笾辽僖?jīng)過兩次標(biāo)記
過程。

15. JAVA中的四種引用類型?

  1. 強(qiáng)引用,把一個(gè)對象賦給一個(gè)引用變量,這個(gè)引用變量就是一個(gè)強(qiáng)引用。當(dāng)一個(gè)對象被強(qiáng)引用變量引用時(shí),它處于可達(dá)狀態(tài),它是不可能被垃圾回收機(jī)制回收的,即
    使該對象以后永遠(yuǎn)都不會被用到 JVM 也不會回收。

  2. 軟引用,用SoftReference實(shí)現(xiàn),當(dāng)系統(tǒng)內(nèi)存足夠時(shí)它
    不會被回收,當(dāng)系統(tǒng)內(nèi)存空間不足時(shí)它會被回收。軟引用通常用在對內(nèi)存敏感的程序中。

  3. 弱引用,弱引用需要用 WeakReference 類來實(shí)現(xiàn),它比軟引用的生存期更短,對于只有弱引用的對象
    來說,只要垃圾回收機(jī)制一運(yùn)行,不管 JVM 的內(nèi)存空間是否足夠,總會回收該對象占用的內(nèi)存。

  4. 虛引用,虛引用需要 PhantomReference 類來實(shí)現(xiàn),它不能單獨(dú)使用,必須和引用隊(duì)列聯(lián)合使用。 虛
    引用的主要作用是跟蹤對象被垃圾回收的狀態(tài)。

16. JAVA類加載機(jī)制?

JVM 類加載機(jī)制分為五個(gè)部分:加載,驗(yàn)證,準(zhǔn)備,解析,初始化。

  1. 加載, 這個(gè)階段會在內(nèi)存中生成一個(gè)代表這個(gè)類的 java.lang.Class 作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的入口。

  2. 驗(yàn)證,確保 Class文件的字節(jié)流中包含的信息是否符合當(dāng)前虛擬機(jī)的要求

  3. 準(zhǔn)備,是正式為類變量分配內(nèi)存并設(shè)置類變量的初始值階段,public static int v = 8080,實(shí)際上變量 v 在準(zhǔn)備階段過后的初始值為 0 而不是 8080,但是如果聲明的是常量就是8080,例如public static final int v = 8080。

  4. 解析,解析階段是指虛擬機(jī)將常量池中的符號引用替換為直接引用的過程。

17. 什么是雙親委派機(jī)制?

當(dāng)一個(gè)類收到了類加載請求,他首先不會嘗試自己去加載這個(gè)類,而是把這個(gè)請求委派給父
類去完成,每一個(gè)層次類加載器都是如此,因此所有的加載請求都應(yīng)該傳送到啟動類加載其中,
只有當(dāng)父類加載器反饋?zhàn)约簾o法完成這個(gè)請求的時(shí)候(在它的加載路徑下沒有找到所需加載的
Class), 子類加載器才會嘗試自己去加載。

18. CMS 收集器?

Concurrent mark sweep(CMS)收集器是一種年老代垃圾收集器,其最主要目標(biāo)是獲取最短垃圾 回收停頓時(shí)間,和其他年老代使用標(biāo)記-整理算法不同,它使用多線程的標(biāo)記-清除算法。 最短的垃圾收集停頓時(shí)間可以為交互比較高的程序提高用戶體驗(yàn)。 CMS工作機(jī)制相比其他的垃圾收集器來說更復(fù)雜,整個(gè)過程分為以下4個(gè)階段:

  1. 初始標(biāo)記 只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)的對象,速度很快,仍然需要暫停所有的工作線程。

  2. 并發(fā)標(biāo)記 進(jìn)行GC Roots跟蹤的過程,和用戶線程一起工作,不需要暫停工作線程。

  3. 重新標(biāo)記 為了修正在并發(fā)標(biāo)記期間,因用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動的那一部分對象的標(biāo)記 記錄,仍然需要暫停所有的工作線程。

  4. 并發(fā)清除 清除GC Roots不可達(dá)對象,和用戶線程一起工作,不需要暫停工作線程。由于耗時(shí)最長的并 發(fā)標(biāo)記和并發(fā)清除過程中,垃圾收集線程可以和用戶現(xiàn)在一起并發(fā)工作,所以總體上來看 CMS收集器的內(nèi)存回收和用戶線程是一起并發(fā)地執(zhí)行。

19. G1收集器?

Garbage first 垃圾收集器是目前垃圾收集器理論發(fā)展的最前沿成果,相比與CMS 收集器,G1 收 集器兩個(gè)最突出的改進(jìn)是:

  1. 基于標(biāo)記-整理算法,不產(chǎn)生內(nèi)存碎片。
  2. 可以非常精確控制停頓時(shí)間,在不犧牲吞吐量前提下,實(shí)現(xiàn)低停頓垃圾回收。 G1 收集器避免全區(qū)域垃圾收集,它把堆內(nèi)存劃分為大小固定的幾個(gè)獨(dú)立區(qū)域,并且跟蹤這些區(qū)域 的垃圾收集進(jìn)度,同時(shí)在后臺維護(hù)一個(gè)優(yōu)先級列表,每次根據(jù)所允許的收集時(shí)間,優(yōu)先回收垃圾 最多的區(qū)域。區(qū)域劃分和優(yōu)先級區(qū)域回收機(jī)制,確保 G1 收集器可以在有限時(shí)間獲得最高的垃圾收 集效率。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容