最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM有哪些組成部分示例詳解(面試必問的Java運(yùn)行時(shí)架構(gòu))

 更新時(shí)間:2026年05月12日 08:20:16   作者:Resky0818  
JVM是Java應(yīng)用程序運(yùn)行的核心環(huán)境,因此在Java相關(guān)的面試中,JVM相關(guān)的知識(shí)是經(jīng)常被考察的重點(diǎn),下面這篇文章主要介紹了JVM有哪些組成部分,文中通過代碼介紹介紹的非常詳細(xì),需要的朋友可以參考下

前言

我剛學(xué) Java 的時(shí)候,以為 JVM 就是個(gè)"黑盒",代碼寫完往里一扔就能跑。

后來才知道,JVM 里面學(xué)問大了去了。

今天這篇文章,就是我復(fù)習(xí) JVM 時(shí)整理的筆記。面試問到 JVM 結(jié)構(gòu),如果你只能說出"堆和棧",那大概率要被追問到懷疑人生。

一、先畫個(gè)整體框架

在說每個(gè)組件之前,先把 JVM 的結(jié)構(gòu)捋清楚。

記住這個(gè)圖,這是整個(gè) JVM 的骨架。

三個(gè)核心模塊:

  1. 類加載器(ClassLoader)—— 把 class 文件加載進(jìn)來

  2. 運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Area)—— 分配內(nèi)存,存數(shù)據(jù)

  3. 執(zhí)行引擎(Execution Engine)—— 執(zhí)行字節(jié)碼指令

二、類加載器 ClassLoader

它干什么的?

ClassLoader 負(fù)責(zé)把 .class 文件(字節(jié)碼)加載到內(nèi)存中,轉(zhuǎn)換成 JVM 能認(rèn)識(shí)的數(shù)據(jù)結(jié)構(gòu)。

加載流程:

.java 源文件
    ↓ 編譯
.class 字節(jié)碼文件
    ↓ ClassLoader
內(nèi)存中的 Class 對(duì)象(java.lang.Class)

三個(gè)階段

1. 加載(Loading)

  • 通過類的全限定名找到 class 文件

  • 把字節(jié)流轉(zhuǎn)換成方法區(qū)的數(shù)據(jù)結(jié)構(gòu)

  • 在堆里生成一個(gè) Class 對(duì)象,作為訪問入口

2. 鏈接(Linking)

  • 驗(yàn)證:檢查字節(jié)碼格式是否正確(安全檢查)

  • 準(zhǔn)備:給靜態(tài)變量分配內(nèi)存,設(shè)置默認(rèn)值

  • 解析:把符號(hào)引用替換成直接引用(比如把"方法名"變成內(nèi)存地址)

3. 初始化(Initialization)

  • 執(zhí)行靜態(tài)代碼塊和靜態(tài)變量的賦值

  • 這是真正執(zhí)行代碼的地方

雙親委派模型

這塊是面試高頻追問。

三層類加載器:

加載器負(fù)責(zé)加載例子
Bootstrap ClassLoaderJDK 核心類String, Object
Extension ClassLoaderJDK 擴(kuò)展類javax.*
Application ClassLoader用戶 classpath自己寫的類

雙親委派流程:

加載請(qǐng)求
   ↓
ApplicationClassLoader
   ↓ 問爸
ExtensionClassLoader
   ↓ 問爸
BootstrapClassLoader
   ↓ 找不到
ExtensionClassLoader 嘗試加載
   ↓ 找不到
ApplicationClassLoader 嘗試加載
   ↓ 成功
返回 Class

為什么這樣設(shè)計(jì)?

我當(dāng)初也被問懵了,后來想明白了一個(gè)例子:

如果你自己寫一個(gè) java.lang.String,沒有雙親委派的話,JVM 就會(huì)加載你自己寫的 String,安全性全沒了。

雙親委派保證:核心類庫優(yōu)先被 Bootstrap 加載,防止用戶代碼覆蓋 JDK。

三、運(yùn)行時(shí)數(shù)據(jù)區(qū) Runtime Data Area

這是 JVM 里最重要的部分,也是面試追問的重災(zāi)區(qū)。

1. 程序計(jì)數(shù)器(Program Counter Register)

特點(diǎn):

  • 很小,只存一個(gè)指針

  • 指向下一條要執(zhí)行的字節(jié)碼指令

  • 線程私有:每個(gè)線程都有自己的 PC

為什么不會(huì) OOM?

因?yàn)樗淮嬉粋€(gè)指令地址,大小固定,不會(huì)動(dòng)態(tài)增長(zhǎng)。

唯一沒有 GC 的區(qū)域。

2. 虛擬機(jī)棧(VM Stack)

特點(diǎn):

  • 線程私有

  • 存儲(chǔ)方法調(diào)用的數(shù)據(jù)

  • 每個(gè)方法叫一個(gè)棧幀(Stack Frame)

一個(gè)棧幀包含:

  • 局部變量表(方法參數(shù) + 局部變量)

  • 操作數(shù)棧(計(jì)算時(shí)的臨時(shí)空間)

  • 動(dòng)態(tài)鏈接(指向常量池的引用)

  • 返回地址

會(huì) OOM 嗎?

會(huì)。如果遞歸沒寫好,棧深度超過限制,就會(huì) StackOverflowError。

我之前寫遞歸算法就踩過這個(gè)坑:

// 死遞歸,棧溢出
public int sum(int n) {
 ? ?return sum(n) + 1; ?// 沒有終止條件
}

3. 本地方法棧(Native Method Stack)

和虛擬機(jī)棧一樣,只不過服務(wù)的是本地方法(native keyword 修飾的方法)。

JNI 調(diào)用(C/C++ 寫的代碼)會(huì)用到這里。

4. 堆(Heap)

JVM 里最大的內(nèi)存區(qū)域。

  • 存儲(chǔ)對(duì)象實(shí)例和數(shù)組

  • 線程共享:所有線程都能訪問

  • GC 的主要戰(zhàn)場(chǎng)

為什么要分代?

因?yàn)閷?duì)象的生命周期不同:

  • 新生代:剛創(chuàng)建的對(duì)象(朝生夕死)

  • 老年代:存活時(shí)間長(zhǎng)的對(duì)象

  • 分代后,GC 更有針對(duì)性,效率更高

5. 方法區(qū)(Method Area)

存儲(chǔ):

  • 類的元信息(類名、修飾符、父類)

  • 類的結(jié)構(gòu)(字段、方法)

  • 運(yùn)行時(shí)常量池(字面量和符號(hào)引用)

  • JIT 編譯后的代碼緩存

JDK 1.8 的變化:

之前方法區(qū)在堆里,叫 Permanent Generation(永久代)。

JDK 1.8 改成了 Metaspace,放在本地內(nèi)存里。

版本方法區(qū)實(shí)現(xiàn)位置
JDK 1.7PermGen堆內(nèi)
JDK 1.8Metaspace本地內(nèi)存

為什么要改?

因?yàn)?PermGen 容易 OOM。你要是項(xiàng)目中依賴了一堆 jar 包,PermGen 分分鐘爆掉。

四、執(zhí)行引擎 Execution Engine

它干什么的?

把字節(jié)碼翻譯成機(jī)器碼,讓 CPU 執(zhí)行。

解釋器 vs JIT 編譯器

組件特點(diǎn)適用場(chǎng)景
解釋器逐行翻譯,立即執(zhí)行啟動(dòng)階段,一次性執(zhí)行
JIT 編譯器編譯成機(jī)器碼,緩存起來熱點(diǎn)代碼,多次執(zhí)行

JIT 的熱點(diǎn)探測(cè):

JVM 會(huì)監(jiān)控方法的執(zhí)行頻率,熱點(diǎn)代碼會(huì)被 JIT 編譯成機(jī)器碼。

兩個(gè)計(jì)數(shù)器:

  • 方法調(diào)用計(jì)數(shù)器

  • 回邊計(jì)數(shù)器(循環(huán)體)

超過閾值就觸發(fā)編譯。

垃圾回收器

GC 是 JVM 里最復(fù)雜也最常問的部分。

常見 GC 算法:

算法原理缺點(diǎn)
標(biāo)記-清除標(biāo)記存活對(duì)象,清理未標(biāo)記的產(chǎn)生內(nèi)存碎片
復(fù)制把活對(duì)象復(fù)制到另一半空間浪費(fèi)一半內(nèi)存
標(biāo)記-整理標(biāo)記后整理內(nèi)存整理耗時(shí)

常見垃圾回收器:

  • Serial(單線程)

  • Parallel(多線程,吞吐量?jī)?yōu)先)

  • CMS(并發(fā)標(biāo)記清除,低停頓)

  • G1(REGION劃分,可預(yù)測(cè)停頓)

  • ZGC / Shenandoah(超低停頓,JDK 11+)

五、本地接口 JNI

Java 不是萬能的,有些場(chǎng)景需要調(diào)用本地代碼(C/C++)。

JNI 就是 Java 和 native 代碼之間的橋梁。

典型場(chǎng)景:

  • 調(diào)用操作系統(tǒng) API

  • 追求極致性能(數(shù)學(xué)計(jì)算)

  • 訪問硬件

public native String hello(); ?// native 方法,調(diào)用 C 實(shí)現(xiàn)

六、記憶口訣

JVM 三大部分:
┌─────────────────────────────────┐
│  類加載器 ──── 加載字節(jié)碼       │
│  運(yùn)行時(shí)數(shù)據(jù)區(qū) ── 分配內(nèi)存       │
│  執(zhí)行引擎 ──── 執(zhí)行字節(jié)碼       │
└─────────────────────────────────┘
?
運(yùn)行時(shí)數(shù)據(jù)區(qū)五塊:
計(jì)數(shù)器(無GC)
虛擬機(jī)棧(存方法調(diào)用,會(huì)OOM)
本地方法棧(native方法)
堆(對(duì)象,會(huì)GC)
方法區(qū)(類信息)
?
雙親委派:
Bootstrap → Extension → Application

寫在最后

JVM 這塊知識(shí),面試基本必問。

我踩過的坑是:只背概念,不畫圖。

后來我把 JVM 的結(jié)構(gòu)畫了 5 遍,把每個(gè)區(qū)域的作用、特點(diǎn)、常見問題都寫上,面試時(shí)直接畫給面試官看。

面試官當(dāng)時(shí)眼睛一亮,說:"這個(gè)理解方式不錯(cuò)。"

技術(shù)表達(dá)很重要。能畫出來、講清楚,比背出來強(qiáng) 100 倍。

到此這篇關(guān)于JVM有哪些組成部分的文章就介紹到這了,更多相關(guān)JVM組成部分內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在macOS上安裝jenv管理JDK版本的詳細(xì)步驟

    在macOS上安裝jenv管理JDK版本的詳細(xì)步驟

    jEnv是一個(gè)命令行工具,正如它的官網(wǎng)所宣稱的那樣,它是來讓你忘記怎么配置JAVA_HOME環(huán)境變量的神隊(duì)友,這篇文章主要介紹了在macOS上安裝jenv管理JDK版本的詳細(xì)步驟,需要的朋友可以參考下
    2025-07-07
  • java實(shí)現(xiàn)的AES加密算法完整實(shí)例

    java實(shí)現(xiàn)的AES加密算法完整實(shí)例

    這篇文章主要介紹了java實(shí)現(xiàn)的AES加密算法,結(jié)合完整實(shí)例形式分析了AES加密類的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • Windows系統(tǒng)編寫bat腳本啟動(dòng)、停止及重啟Java服務(wù)jar包

    Windows系統(tǒng)編寫bat腳本啟動(dòng)、停止及重啟Java服務(wù)jar包

    在bat文件中我們將編寫一些代碼來運(yùn)行Java jar文件,下面這篇文章主要給大家介紹了關(guān)于Windows系統(tǒng)編寫bat腳本啟動(dòng)、停止及重啟Java服務(wù)jar包的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • Component-Scan 不掃描jar里面的類問題

    Component-Scan 不掃描jar里面的類問題

    這篇文章主要介紹了Component-Scan 不掃描jar里面的類問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java list去重操作實(shí)現(xiàn)方式

    java list去重操作實(shí)現(xiàn)方式

    Java中的List是可以包含重復(fù)元素的(hash code 和equals),接下來將介紹兩種方式實(shí)現(xiàn)java list去重操作,感興趣的朋友可以參考下
    2012-12-12
  • Java中使用HttpGet發(fā)起HTTP請(qǐng)求的適用場(chǎng)景詳解

    Java中使用HttpGet發(fā)起HTTP請(qǐng)求的適用場(chǎng)景詳解

    HttpGet是HTTP協(xié)議中用于獲取服務(wù)器資源的GET請(qǐng)求實(shí)現(xiàn),屬于Java的HttpClient庫核心類之一,本文圍繞HttpGet的基本使用展開,詳細(xì)介紹了HTTP請(qǐng)求的結(jié)構(gòu)、HttpGet的創(chuàng)建與配置、請(qǐng)求執(zhí)行流程、響應(yīng)處理方式,以及資源釋放和異常處理的關(guān)鍵步驟,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • ElasticSearch學(xué)習(xí)之多條件組合查詢驗(yàn)證及示例分析

    ElasticSearch學(xué)習(xí)之多條件組合查詢驗(yàn)證及示例分析

    這篇文章主要為大家介紹了ElasticSearch 多條件組合查詢驗(yàn)證及示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • SpringBoot中的靜態(tài)資源訪問的實(shí)現(xiàn)

    SpringBoot中的靜態(tài)資源訪問的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot中的靜態(tài)資源訪問的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 關(guān)于Spring Bean實(shí)例過程中使用反射和遞歸處理的Bean屬性填充問題

    關(guān)于Spring Bean實(shí)例過程中使用反射和遞歸處理的Bean屬性填充問題

    本文帶領(lǐng)大家一起學(xué)習(xí)下在Spring Bean實(shí)例過程中如何使用反射和遞歸處理的Bean屬性填充,需要在類 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加補(bǔ)全屬性方法,具體操作方法跟隨小編一起學(xué)習(xí)下吧
    2021-06-06
  • 梳理總結(jié)Java?static關(guān)鍵字的方法作用

    梳理總結(jié)Java?static關(guān)鍵字的方法作用

    這篇文章主要介紹了梳理總結(jié)Java?static關(guān)鍵字的方法作用,?static?關(guān)鍵字可以用來修飾的成員變量和成員方法,被修飾的成員是屬于類的,而不是單單是屬于某個(gè)對(duì)象的
    2022-06-06

最新評(píng)論

静安区| 文水县| 九寨沟县| 瓮安县| 磐安县| 海丰县| 茂名市| 东丽区| 瑞安市| 汝南县| 贵定县| 景泰县| 墨竹工卡县| 鄂州市| 温州市| 牡丹江市| 六枝特区| 阿合奇县| 武邑县| 尚义县| 崇文区| 交口县| 彩票| 大同市| 若羌县| 改则县| 横山县| 静海县| 临沧市| 巴东县| 渝中区| 谢通门县| 咸阳市| 宜兴市| 娱乐| 永兴县| 石台县| 凤阳县| 沽源县| 武汉市| 广河县|