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

面試必問的Java 運(yùn)行時(shí)架構(gòu)JVM詳解

 更新時(shí)間:2026年04月27日 09:18:20   作者:Resky0818  
本文主要介紹了Java虛擬機(jī)(JVM的結(jié)構(gòu)、運(yùn)行時(shí)數(shù)據(jù)區(qū)、執(zhí)行引擎等相關(guān)知識,JVM主要由類加載器、運(yùn)行時(shí)數(shù)據(jù)區(qū)、執(zhí)行引擎和本地接口等組成,感興趣的朋友跟隨小編一起看看吧

我剛學(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è)核心模塊:

  • 類加載器(ClassLoader)—— 把 class 文件加載進(jìn)來
  • 運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Area)—— 分配內(nèi)存,存數(shù)據(jù)
  • 執(zhí)行引擎(Execution Engine)—— 執(zhí)行字節(jié)碼指令

二、類加載器 ClassLoader

它干什么的?

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

加載流程:

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

三個(gè)階段

1. 加載(Loading)

  • 通過類的全限定名找到 class 文件
  • 把字節(jié)流轉(zhuǎn)換成方法區(qū)的數(shù)據(jù)結(jié)構(gòu)
  • 在堆里生成一個(gè) Class 對象,作為訪問入口

2. 鏈接(Linking)

  • 驗(yàn)證:檢查字節(jié)碼格式是否正確(安全檢查)
  • 準(zhǔn)備:給靜態(tài)變量分配內(nèi)存,設(shè)置默認(rèn)值
  • 解析:把符號引用替換成直接引用(比如把"方法名"變成內(nèi)存地址)

3. 初始化(Initialization)

  • 執(zhí)行靜態(tài)代碼塊和靜態(tài)變量的賦值
  • 這是真正執(zhí)行代碼的地方

雙親委派模型

這塊是面試高頻追問。

三層類加載器:

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

雙親委派流程:

加載請求
 ?  ↓
ApplicationClassLoader
 ?  ↓ 問爸
ExtensionClassLoader
 ?  ↓ 問爸
BootstrapClassLoader
 ?  ↓ 找不到
ExtensionClassLoader 嘗試加載
 ?  ↓ 找不到
ApplicationClassLoader 嘗試加載
 ?  ↓ 成功
返回 Class

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

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

如果你自己寫一個(gè) java.lang.String,沒有雙親委派的話,JVM 就會加載你自己寫的 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

為什么不會 OOM?

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

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

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

特點(diǎn):

  • 線程私有
  • 存儲方法調(diào)用的數(shù)據(jù)
  • 每個(gè)方法叫一個(gè)棧幀(Stack Frame)

一個(gè)棧幀包含:

  • 局部變量表(方法參數(shù) + 局部變量)
  • 操作數(shù)棧(計(jì)算時(shí)的臨時(shí)空間)
  • 動(dòng)態(tài)鏈接(指向常量池的引用)
  • 返回地址

會 OOM 嗎?

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

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

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

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

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

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

4. 堆(Heap)

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

  • 存儲對象實(shí)例和數(shù)組
  • 線程共享:所有線程都能訪問
  • GC 的主要戰(zhàn)場

為什么要分代?

因?yàn)閷ο蟮纳芷诓煌?/p>

  • 新生代:剛創(chuàng)建的對象(朝生夕死)
  • 老年代:存活時(shí)間長的對象
  • 分代后,GC 更有針對性,效率更高

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

存儲:

  • 類的元信息(類名、修飾符、父類)
  • 類的結(jié)構(gòu)(字段、方法)
  • 運(yùn)行時(shí)常量池(字面量和符號引用)
  • 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)適用場景
解釋器逐行翻譯,立即執(zhí)行啟動(dòng)階段,一次性執(zhí)行
JIT 編譯器編譯成機(jī)器碼,緩存起來熱點(diǎn)代碼,多次執(zhí)行

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

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

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

  • 方法調(diào)用計(jì)數(shù)器
  • 回邊計(jì)數(shù)器(循環(huán)體)

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

垃圾回收器

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

常見 GC 算法:

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

常見垃圾回收器:

  • Serial(單線程)
  • Parallel(多線程,吞吐量優(yōu)先)
  • CMS(并發(fā)標(biāo)記清除,低停頓)
  • G1(REGION劃分,可預(yù)測停頓)
  • ZGC / Shenandoah(超低停頓,JDK 11+)

五、本地接口 JNI

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

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

典型場景:

  • 調(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)用,會OOM)
本地方法棧(native方法)
堆(對象,會GC)
方法區(qū)(類信息)
雙親委派:
Bootstrap → Extension → Application

寫在最后

JVM 這塊知識,面試基本必問。

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

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

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

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

到此這篇關(guān)于JVM 有哪些組成部分:面試必問的 Java 運(yùn)行時(shí)架構(gòu)的文章就介紹到這了,更多相關(guān)java運(yùn)行時(shí)架構(gòu)jvm內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java安全 ysoserial CommonsCollections3示例分析

    Java安全 ysoserial CommonsCollections3示例分析

    這篇文章主要為大家介紹了Java安全 ysoserial CommonsCollections3示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • java中map與實(shí)體類的相互轉(zhuǎn)換操作

    java中map與實(shí)體類的相互轉(zhuǎn)換操作

    這篇文章主要介紹了java中map與實(shí)體類的相互轉(zhuǎn)換操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java通過Caffeine和自定義注解實(shí)現(xiàn)本地防抖接口限流

    Java通過Caffeine和自定義注解實(shí)現(xiàn)本地防抖接口限流

    Caffeine?是目前Java領(lǐng)域最熱門,性能最高的本地內(nèi)存緩存庫,本文為大家詳細(xì)介紹了如何利用Caffeine和自定義注解實(shí)現(xiàn)本地防抖接口限流功能,需要的可以了解下
    2025-05-05
  • MyBatis處理懶加載和預(yù)加載的實(shí)戰(zhàn)詳解

    MyBatis處理懶加載和預(yù)加載的實(shí)戰(zhàn)詳解

    在Java開發(fā)中,MyBatis是一個(gè)廣泛使用的持久層框架,它為開發(fā)者提供了靈活、強(qiáng)大的數(shù)據(jù)訪問能力,兩種常用的加載策略是懶加載和預(yù)加載,本文將介紹這兩種加載方式的概念、適用場景以及MyBatis中的實(shí)現(xiàn)方式,需要的朋友可以參考下
    2026-02-02
  • 深入理解java動(dòng)態(tài)代理的兩種實(shí)現(xiàn)方式(JDK/Cglib)

    深入理解java動(dòng)態(tài)代理的兩種實(shí)現(xiàn)方式(JDK/Cglib)

    本篇文章主要介紹了java動(dòng)態(tài)代理的兩種實(shí)現(xiàn)方式,詳細(xì)的介紹了JDK和Cglib的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-04-04
  • java字符串日期類Date和Calendar相互轉(zhuǎn)化及相關(guān)常用方法

    java字符串日期類Date和Calendar相互轉(zhuǎn)化及相關(guān)常用方法

    Java語言的Calendar(日歷),Date(日期),和DateFormat(日期格式)組成了Java標(biāo)準(zhǔn)的一個(gè)基本但是非常重要的部分,下面這篇文章主要給大家介紹了關(guān)于java字符串日期類Date和Calendar相互轉(zhuǎn)化及相關(guān)常用方法的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • 匯總Java中List 去重的 6 種方法

    匯總Java中List 去重的 6 種方法

    這篇文章主要介紹了匯總Java中List 去重的 6 種方法,文章圍繞主題展開List去重的方法,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • 解讀@ResponseBody與@RequestBody注解的用法

    解讀@ResponseBody與@RequestBody注解的用法

    這篇文章主要介紹了Spring MVC中的@ResponseBody和@RequestBody注解的用法,@ResponseBody注解用于將Controller方法的返回對象轉(zhuǎn)換為指定格式(如JSON)并通過Response響應(yīng)給客戶端,@RequestBody注解用于讀取HTTP請求的內(nèi)容
    2024-11-11
  • java springmvc實(shí)現(xiàn)驗(yàn)證碼功能

    java springmvc實(shí)現(xiàn)驗(yàn)證碼功能

    這篇文章主要為大家詳細(xì)介紹了java springmvc實(shí)現(xiàn)驗(yàn)證碼功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • IDEA中實(shí)體類(POJO)與JSON快速互轉(zhuǎn)問題

    IDEA中實(shí)體類(POJO)與JSON快速互轉(zhuǎn)問題

    這篇文章主要介紹了IDEA中實(shí)體類(POJO)與JSON快速互轉(zhuǎn),本文通過圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08

最新評論

临夏县| 安化县| 大庆市| 梨树县| 海丰县| 威信县| 会宁县| 济南市| 清河县| 昂仁县| 福清市| 财经| 锡林浩特市| 新竹市| 顺昌县| 北安市| 盈江县| 彰化县| 连州市| 察雅县| 健康| 天祝| 屯留县| 北票市| 嵩明县| 武穴市| 南京市| 房山区| 基隆市| 日喀则市| 延边| 昔阳县| 余庆县| 武强县| 延安市| 襄汾县| 探索| 阳谷县| 临沧市| 浮山县| 淮南市|