JVM——八股文

1. JDK, JRE和JVM的關系

  • JDK = JRE + Java開發工具
  • JRE = JVM + Java核心類庫

JDK供Java程序開發人員開發軟件,JRE供客戶使用,只需要JVM運行環境即可。

JVM運行的是class字節碼,不僅能運行Java代碼,還能運行其他語言,只要語言能編譯成字節碼文件即可,比如Kotlin。

2. JVM的主要組成部分

  • 類加載器
    • 加載Loading
    • 鏈接Linking
    • 初始化Initialization
  • 運行時數據區
  • 執行引擎
  • 本地接口

3. 你能解釋一下JVM類加載器的作用嗎

1. 加載 (Loading)

  • 目的:將類的?.class?文件的二進制數據讀入內存,并在方法區中創建一個?java.lang.Class?對象來表示這個類。
  • 主要工作
    1. 通過類的全限定名獲取其二進制字節流:這可以通過多種方式實現,比如從本地?.class?文件、JAR 包、網絡、動態生成(如?Proxy?類)、數據庫等。
    2. 將字節流代表的靜態存儲結構轉化為方法區的運行時數據結構:JVM 解析字節碼,并在方法區(Method Area)或元空間(Metaspace,Java 8+)中創建該類的數據結構。
    3. 在內存中創建一個?java.lang.Class?對象:這個對象是?java.lang.Class?的實例,它作為程序訪問該類各種數據的入口。這個對象通常存儲在堆(Heap)中。
  • 關鍵點
    • 這個階段主要由類加載器(ClassLoader)?完成。
    • 類加載器遵循雙親委派模型(Parent Delegation Model),即先委托父類加載器嘗試加載,只有當父類加載器無法完成時,子加載器才會嘗試自己加載。

2. 鏈接 (Linking)

鏈接階段確保加載的類是正確且符合 JVM 規范的,并為其分配內存。它分為三個子階段:

(1) 驗證 (Verification)

  • 目的:確保?.class?文件的字節流包含的信息符合當前 JVM 的要求,不會危害 JVM 的安全。
  • 主要檢查
    • 文件格式驗證:檢查字節流是否符合?.class?文件格式規范(如魔數?0xCAFEBABE、版本號等)。
    • 元數據驗證:檢查類的元數據信息是否有矛盾(如是否繼承了?final?類、是否實現了不存在的接口等)。
    • 字節碼驗證:這是最復雜和關鍵的一步。通過數據流和控制流分析,確定字節碼指令不會做出危害 JVM 安全的操作(如類型轉換錯誤、非法跳轉、訪問不存在的字段等)。
    • 符號引用驗證:確保解析動作能正常執行(如檢查符號引用中描述的類、字段、方法是否存在)。
  • 重要性:這是 JVM 防止惡意代碼攻擊的重要屏障。雖然驗證很耗時,但可以保證運行時的安全性。

(2) 準備 (Preparation)

  • 目的:為類的靜態變量static?fields)分配內存,并設置這些變量的初始值
  • 關鍵點
    • 分配內存:在方法區(或元空間)為?static?變量分配內存。
    • 設置初始值:這里的“初始值”通常是零值(zero value),而不是你在代碼中賦的值。
      • int?類型的?static?變量初始值為?0
      • boolean?類型的?static?變量初始值為?false
      • 引用類型(Object)的?static?變量初始值為?null
    • final static?常量:如果?static?變量同時被?final?修飾,并且是基本類型或?String?字面量,那么它的值(編譯期常量)會在這個階段直接賦值,而不是零值。例如:public static final int MAX = 100;?的值?100?會在準備階段就設置好。

(3) 解析 (Resolution)

  • 目的:將常量池內的符號引用(Symbolic References)替換為直接引用(Direct References)。
  • 概念解釋
    • 符號引用:以一組符號來描述所引用的目標。它可以是任何形式的字面量,只要能無歧義地定位到目標即可。例如,常量池中用?類名.方法名.描述符?來表示一個方法。
    • 直接引用:可以直接指向目標的指針、相對偏移量或一個能間接定位到目標的句柄。直接引用是與內存布局相關的。
  • 解析的內容
    • 類或接口解析:將符號引用解析為具體的類或接口的?Class?對象。
    • 字段解析:將符號引用解析為字段在類中的內存偏移量。
    • 方法解析:將符號引用解析為方法在方法表中的索引或直接指針。
    • 接口方法解析:類似方法解析。
  • 時機:解析動作不一定在鏈接階段一次性完成,它可能在初始化之后才進行(稱為“延遲解析”或“惰性解析”)。只有當真正需要使用某個符號引用時,才會觸發解析。

3. 初始化 (Initialization)

  • 目的:執行類的初始化代碼,為類的靜態變量賦予程序中指定的值,并執行?static?代碼塊。
  • 主要工作
    • 執行?<clinit>()?方法。<clinit>?是由編譯器自動收集類中所有?static?變量的賦值語句和?static?代碼塊中的語句合并產生的類構造器方法。
    • 按照代碼中出現的順序執行這些初始化語句。
  • 關鍵點
    • 這是類加載過程的最后一步
    • <clinit>()?方法是線程安全的:JVM 會保證一個類的?<clinit>()?方法在多線程環境下只被執行一次。其他線程會阻塞,直到第一個線程完成初始化。
    • 觸發時機:這是主動使用一個類的時刻。以下操作會觸發類的初始化:
      1. 創建類的實例(new?關鍵字)。
      2. 訪問類的靜態變量(public static?除外,final static?編譯期常量也不會觸發)。
      3. 調用類的靜態方法。
      4. 使用反射(Class.forName())。
      5. 初始化一個類的子類(會先觸發父類的初始化)。
      6. 虛擬機啟動時,包含?main()?方法的主類。
      7. MethodHandle?和?VarHandle?的某些操作。
    • 被動引用不會觸發:訪問?final static?編譯期常量、通過子類引用父類的?static?變量(只會觸發父類初始化,不會觸發子類)、數組定義(new MyClass[10]?不會觸發?MyClass?的初始化)等屬于被動引用,不會觸發初始化。

4. 使用 (Using)

  • 目的:類初始化完成后,就可以被程序正常使用了。
  • 工作:程序通過?new?創建對象、調用靜態方法、訪問實例方法等。

5. 卸載 (Unloading)?

  • 目的:當類不再被任何地方引用,滿足垃圾回收條件時,JVM 可以卸載該類,回收其占用的內存(主要是方法區/元空間和?Class?對象本身)。
  • 條件:非常嚴格。需要該類的?ClassLoader?被回收、該類的所有實例都已被回收、該類的?Class?對象沒有被任何地方引用。

總結流程圖

加載 (Loading)↓
鏈接 (Linking)├── 驗證 (Verification)├── 準備 (Preparation)  <-- static 變量賦零值 (或 final static 常量值)└── 解析 (Resolution)   <-- 符號引用 -> 直接引用↓
初始化 (Initialization)    <-- 執行 <clinit>(), static 變量賦程序值, 執行 static 塊↓
使用 (Using)↓
卸載 (Unloading) (可選)

4. 你知道JVM的類加載器有哪些?雙親委派機制是什么?

一、JVM 的類加載器 (Class Loaders)

JVM 在啟動時會創建一系列的類加載器,它們形成了一個層次結構。主要的類加載器有三種(從頂層到底層):

1. 啟動類加載器 (Bootstrap ClassLoader)

  • 角色:最頂層的類加載器,是 JVM?自身的一部分,通常由 C/C++ 實現。
  • 負責加載
    • JAVA_HOME/lib?目錄下的核心類庫(如?rt.jar,?tools.jar,?resources.jar?等)。
    • 或者被?-Xbootclasspath?參數指定的路徑中的類庫。
  • 特點
    • 用 C/C++ 編寫,不是 Java 類,因此在 Java 代碼中無法直接引用它(getClassLoader()?返回?null)。
    • 負責加載最基礎、最核心的 Java 類(如?java.lang.*,?java.util.*,?java.io.*?等)。

2. 擴展類加載器 (Extension ClassLoader)

  • 角色Bootstrap ClassLoader?的子加載器,由 Java 實現。
  • 負責加載
    • JAVA_HOME/lib/ext?目錄下的類庫。
    • 或者被?java.ext.dirs?系統變量所指定的路徑中的所有類庫。
  • 特點
    • 允許開發者將具有通用功能的 JAR 包放在這個目錄下,自動被加載,無需在?-classpath?中指定。
    • 在 Java 9 的模塊化系統(JPMS)之后,其重要性有所下降。

3. 應用程序類加載器 (Application ClassLoader) / 系統類加載器 (System ClassLoader)

  • 角色Extension ClassLoader?的子加載器,也是 Java 實現。
  • 負責加載
    • 用戶類路徑(ClassPath)上所指定的類庫。
    • 即我們通常通過?-classpath?或?-cp?參數指定的?.jar?文件或?.class?文件目錄。
  • 特點
    • 這是默認的類加載器,我們編寫的 Java 類和第三方依賴庫(如 Maven/Gradle 依賴)通常由它加載。
    • 可以通過?ClassLoader.getSystemClassLoader()?獲取它的實例。

(可選) 自定義類加載器 (Custom ClassLoader)

  • 角色:開發者可以繼承?java.lang.ClassLoader?類來創建自己的類加載器。
  • 目的
    • 從非標準來源加載類(如網絡、數據庫、加密的 JAR 包)。
    • 實現類的隔離(如 Tomcat 的 Web 應用隔離、OSGi 模塊化)。
    • 實現熱部署(Hot Swap)。
  • 常用場景:Web 服務器(Tomcat, Jetty)、應用服務器(WebLogic, WebSphere)、插件化框架、熱更新系統。

二、雙親委派機制 (Parent Delegation Model)

雙親委派機制是 JVM 類加載器加載類時遵循的一種工作模式。它的核心思想是:當一個類加載器收到類加載請求時,它不會自己先去加載,而是把這個請求委派給它的父類加載器去完成,每一層的類加載器都是如此,因此所有的加載請求最終都會傳送到頂層的啟動類加載器。只有當父類加載器無法完成這個加載請求(即在它的搜索路徑下找不到所需的類)時,子加載器才會嘗試自己去加載。

工作流程

  1. 發起請求:假設應用程序類加載器(AppClassLoader)收到一個加載?java.lang.String?的請求。
  2. 向上委派:AppClassLoader 不會直接加載,而是將請求委派給它的父加載器——擴展類加載器(ExtClassLoader)。
  3. 繼續委派:ExtClassLoader 收到請求后,也不會直接加載,而是繼續委派給它的父加載器——啟動類加載器(Bootstrap ClassLoader)。
  4. 頂層嘗試加載:Bootstrap ClassLoader 嘗試在?rt.jar?等核心庫中查找?java.lang.String,找到了,于是加載成功,返回?Class?對象。
  5. 逐層返回:加載結果從 Bootstrap ClassLoader 逐層返回給 ExtClassLoader,再返回給 AppClassLoader,最終返回給發起請求的代碼。

如果父加載器找不到呢?

  • 假設請求加載一個用戶自定義的類?com.example.MyClass
  • 請求最終傳到 Bootstrap ClassLoader,它在核心庫中找不到。
  • Bootstrap ClassLoader 返回失敗。
  • 請求返回到 ExtClassLoader,它在?lib/ext?目錄下也找不到。
  • 請求返回到 AppClassLoader,它在 ClassPath 下找到了?com.example.MyClass.class,于是由它自己加載。

為什么需要雙親委派機制?

  1. 避免類的重復加載

    • 保證一個類在 JVM 中只有一個唯一的?Class?對象。
    • 例如,無論哪個類加載器發起加載?java.lang.Object?的請求,最終都會由 Bootstrap ClassLoader 加載,確保所有地方使用的都是同一個?Object?類。
  2. 保證核心類庫的安全性

    • 這是最關鍵的一點。它防止了惡意代碼通過自定義類加載器來替換核心 Java 類。
    • 例如,你不能自己寫一個?java.lang.String?類放在 ClassPath 下,期望它被加載。因為當請求到達時,Bootstrap ClassLoader 會先加載它自己的、可信的?String?類,你的惡意類永遠沒有機會被加載。
    • 這確保了 Java 核心 API 的穩定性和安全性

如何打破雙親委派?

雖然雙親委派是默認和推薦的模式,但在某些特殊場景下需要打破它:

  1. 基礎類型回調用戶代碼

    • 典型例子JNDI?(Java Naming and Directory Interface)。
    • JNDI?的核心類由 Bootstrap ClassLoader 加載,但它需要回調由應用程序提供的服務實現(SPI - Service Provider Interface)。
    • Bootstrap ClassLoader 無法加載應用類路徑下的類。
    • 解決方案:通過線程上下文類加載器Thread.currentThread().getContextClassLoader())。這個加載器通常被設置為 AppClassLoader。JNDI?核心代碼可以通過它來加載用戶實現的 SPI 類,從而“逆向”委托。
  2. 實現熱部署/模塊化

    • 典型例子:Tomcat, OSGi。
    • 需要隔離不同 Web 應用或模塊的類,避免相互影響和核心庫沖突。
    • 解決方案:自定義類加載器,并重寫?loadClass()?方法,改變委派邏輯。例如,Tomcat 的 Web 應用類加載器會優先嘗試自己加載 Web 應用的類(/WEB-INF/classes,?/WEB-INF/lib),只有當自己找不到時,才委派給父加載器(打破了“先委派”的原則)。這實現了應用間的類隔離。

總結

  • 類加載器:Bootstrap -> Extension -> Application -> Custom,形成層次結構。
  • 雙親委派:加載請求優先向上委派給父加載器,父加載器無法完成時,子加載器才嘗試自己加載。
  • 優點:保證類的唯一性、核心類庫安全。
  • 打破場景:SPI(如 JNDI)、熱部署/模塊化(如 Tomcat, OSGi),通常通過線程上下文類加載器或重寫?loadClass()?實現。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97620.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97620.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97620.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

騎行把帶定期換,維樂 Skin Wrap 把帶煥新騎行

在公路騎行的裝備體系里&#xff0c;把帶是最易被忽視卻至關重要的“消耗品”。它是騎手手部與車身的直接連接&#xff0c;每一次轉向、變速、剎車&#xff0c;都需通過把帶傳遞力量與操控意圖&#xff1b;同時&#xff0c;它還承擔著吸汗、減震、保護車把的作用。可長期使用后…

LeetCode100-73矩陣置零

本文基于各個大佬的文章 上點關注下點贊&#xff0c;明天一定更燦爛&#xff01; 前言 Python基礎好像會了又好像沒會&#xff0c;所有我直接開始刷leetcode一邊抄樣例代碼一邊學習吧。本系列文章用來記錄學習中的思考&#xff0c;寫給自己看的&#xff0c;也歡迎大家在評論區指…

寧波市第八屆網絡安全大賽 -- Crypto -- WriteUp

寧波市第八屆網絡安全大賽 – Crypto – WriteUp Three-prime RSA task import gmpy2 from Crypto.Util.number import *from secret import flagp getPrime(512) q getPrime(512) r getPrime(512) n p * q * r random_num getPrime(28) D ((p q r) * random_num) % n …

大語言模型 (LLM) 與多模態大模型 (MLM)

文章目錄概述&#xff1a;從“模型”到“大”模型1、大語言模型 (Large Language Model, LLM)1.1 定義與概述關鍵特征&#xff1a;1.2 核心技術與架構Transformer架構自注意力機制 (Self-Attention)1.3 訓練過程1.4 工作原理2. 多模態大模型 (Multimodal Large Model, MLM)2.1 …

HTML應用指南:利用GET請求獲取全國招商銀行網點位置信息

招商銀行&#xff08;China Merchants Bank, CMB&#xff09;作為中國領先的股份制商業銀行&#xff0c;始終堅持“以客戶為中心”的服務理念&#xff0c;致力于為個人客戶、企業客戶及機構客戶提供專業、高效、便捷的綜合金融服務。依托“輕型銀行”戰略與“金融科技銀行”建設…

JVM性能監控工具的使用

了解JVM性能監控工具并能熟練使用&#xff0c;是Java開發者進階的必備技能。下面本文將為你介紹一些主流的JVM性能監控工具及其使用方法&#xff0c;并通過一些場景案例來分析如何應用這些工具解決實際問題。 &#x1f6e0;? JVM性能監控與調優工具指南 ? 工具概覽 以下是幾款…

【工作】一些找工作需要了解避雷的知識

面試前 1.公司的具體情況 公司全稱&#xff0c;辦公地點&#xff0c;涉及崗位 要求hr做個簡單的公司介紹 2.崗位職責/業務方向 工作內容、公司業務 3.薪資待遇&#xff0c;構成&#xff0c;底薪&#xff0c;五險一金 問一下工資范圍 底薪 &#xff08;有責&#xff0c;無…

五、練習2:Git分支操作

練習2&#xff1a;Git分支操作 練習目標 掌握Git分支的創建、切換、合并等操作&#xff0c;理解分支在開發中的作用。 練習步驟 步驟1&#xff1a;準備基礎倉庫 # 創建練習目錄 mkdir branch-practice cd branch-practice# 初始化倉庫 git init# 創建初始文件 echo "# 分支…

【筆記】算法設計:異或空間線性基

Content1.什么是異或&#xff08;定義和性質&#xff09;2.異或空間線性基的構造方法3.異或空間線性基的應用4.算法設計例舉5.小結說明算法設計應用之前&#xff0c;首先明確異或空間線性基&#xff1a;一種數據結構。用于處理異或關系&#xff08;運算&#xff09;下的向量空間…

Filebeat采集數據與日志分析實戰

&#x1f31f;Filebeat采集數據的原理 Filebeat默認按行采集數據&#xff0c;如果數據沒有換行&#xff0c;則該條數據無法采集到 屬于有狀態服務&#xff0c;可以記錄上一次采集數據的位置點信息 修改配置文件 vim /etc/filebeat/config/03-log-to-console.yaml filebeat.inp…

Fluent Bit針對kafka心跳重連機制詳解(下)

#作者&#xff1a;程宏斌 文章目錄disconnectreconnect接上篇&#xff1a;https://blog.csdn.net/qq_40477248/article/details/150957571?spm1001.2014.3001.5501disconnect 斷開連接的情況主要是兩種: 連接或傳輸過程中有錯誤發生 超時, 比如空閑時間超時 ** * Close and …

React 第七十一節 Router中generatePath的使用詳解及注意事項

前言 generatePath 是 React Router 的一個實用工具函數&#xff0c;用于根據路徑模式和參數對象生成實際的 URL 路徑。它在需要動態構建鏈接的場景中非常有用&#xff0c;比如生成導航鏈接或重定向路徑。 1、基本用法和注意事項 import { generatePath } from react-router-do…

Python 爬蟲案例:爬取豆瓣電影 Top250 數據

一、案例背景與目標 豆瓣電影 Top250 是國內權威的電影評分榜單之一&#xff0c;包含電影名稱、評分、評價人數、導演、主演、上映年份、國家 / 地區、類型等關鍵信息。本案例將使用 Python 編寫爬蟲&#xff0c;實現以下目標&#xff1a; 自動請求豆瓣電影 Top250 的 10 個分…

SPA安全警示:OAuth2.0致命漏洞

OAuth2.0在SPA應用中的安全陷阱SPA&#xff08;單頁應用&#xff09;通常采用隱式授權&#xff08;Implicit Flow&#xff09;或PKCE&#xff08;Proof Key for Code Exchange&#xff09;授權模式&#xff0c;但存在以下安全隱患&#xff1a;隱式授權模式的漏洞訪問令牌直接暴…

table表格字段明細展示

文章目錄1、字段渲染2、異步請求展示明細3、hover展示問題3.1 基本邏輯3.2 hover時長判斷3.3 renderhover表格字段明細展示&#xff0c;屬于比較小的需求&#xff0c;但是也有一定交互細節&#xff0c;本文選取部分場景。 1、字段渲染 render和渲染組件是有區別的。render常見為…

主網上線后生態極速擴張的 Berachain 生態,有哪些值得關注的項目?

Berachain 是典型的將 DeFi 思維嵌入到共識機制中的 Layer1&#xff0c;其核心是 PoL&#xff08;Proof of Liquidity&#xff09;共識。PoL 要求驗證者在獲得區塊獎勵前&#xff0c;必須將流動性導入白名單協議&#xff0c;并由市場決定資金流向。這樣&#xff0c;驗證者的權重…

claude-code對比GitHub-Copilot

Claude Code 文檔日期&#xff1a;2025 年 08 月 20 日 定位 項目級開發助手&#xff0c;專注于全局視野和復雜任務的處理。 特點 超長上下文支持&#xff1a;支持 200k 超長上下文&#xff0c;適合處理復雜項目。豐富的自定義命令&#xff1a;提供靈活的命令配置&#xff0c;滿…

Roo Code自定義Mode(模式)

什么是自定義模式&#xff1f; 簡單來說&#xff0c;自定義模式就像是給Roo Code穿上不同的"職業裝"。你可以創建針對特定任務或工作流程量身定制的模式&#xff0c;讓Roo在不同場景下表現出專業的行為。 這些模式分為兩種類型&#xff1a;全局模式&#xff08;在所有…

Next.js渲染模式:SSR、SSG與ISR揭秘

Next.js 核心渲染模式深度解析&#xff1a;SSR、SSG 與 ISR 在構建現代 Web 應用時&#xff0c;性能和用戶體驗是至關重要的考量。Next.js 作為 React 生態中一個備受推崇的框架&#xff0c;其強大的服務端渲染&#xff08;SSR&#xff09;、靜態站點生成&#xff08;SSG&#…

Veo Videos Generation API 對接說明

本文介紹了如何對接 Veo Videos Generation API&#xff0c;通過輸入自定義參數生成Veo官方視頻。 下面將詳細闡述 Veo Videos Generation API 的對接流程。 申請流程 使用 API 前&#xff0c;需前往 Veo Videos Generation API 頁面申請服務。進入頁面后&#xff0c;點擊「…