深入理解Java虛擬機:Java內存區域與內存溢出異常

前言

Java虛擬機(JVM)的自動內存管理是其核心特性之一,它極大地簡化了開發者的工作,減少了內存泄漏和內存溢出的問題。本文將詳細介紹JVM的自動內存管理機制的內存區域與內存溢出異常問題,包括運行時數據區域、對象的創建、對象的內存布局、對象的訪問定位。

一、運行時數據區域

Java虛擬機(JVM)的運行時數據區域是內存管理的核心模塊,分為以下關鍵部分:


1. 線程私有區域(生命周期與線程綁定)

  1. 程序計數器(PC Register)

    • 記錄當前線程執行的字節碼指令地址(若執行Native方法則為空)。
    • 唯一無OOM的區域(無內存溢出風險)。
  2. 虛擬機棧(Java Stack)

    • 存儲棧幀(Frame),每個方法調用對應一個棧幀,包含:
      • 局部變量表(基本類型/對象引用)
      • 操作數棧(計算中間結果)
      • 動態鏈接(指向方法區符號引用)
      • 方法出口(返回地址)
    • 可能拋出 StackOverflowError(棧深度超限)或 OOM(擴展失敗)。
  3. 本地方法棧(Native Stack)

    • Native方法(如C/C++代碼)提供棧空間。
    • 異常類型同虛擬機棧。

2. 線程共享區域(生命周期與JVM進程綁定)

  1. 堆(Heap)

    • 存放對象實例與數組(占內存最大部分)。
    • 垃圾收集器主要工作區域(GC堆)。
    • 可細分為:
      • 新生代(Eden + Survivor0/1)
      • 老年代(Tenured)
    • 拋出 OOM(無法分配對象且堆無法擴展)。
  2. 方法區(Method Area)

    • 存儲類元數據(類型信息、字段、方法)、常量池靜態變量JIT編譯代碼
    • JDK 8后由元空間(Metaspace)實現(替代永久代),使用本地內存。
    • 拋出 OOM(無法滿足內存分配)。
  3. 運行時常量池(Runtime Constant Pool)

    • 方法區的一部分,存儲編譯期字面量(字符串、數字)和符號引用(類/方法/字段名)。
    • 具備動態性(如String.intern()可在運行時添加常量)。
    • 拋出 OOM(常量池溢出)。

3. 直接內存(Direct Memory)

  • 非JVM運行時數據區,但頻繁使用。
  • 通過ByteBuffer.allocateDirect()分配堆外內存(NIO通道操作時避免復制數據)。
  • 受系統內存限制,拋出 OOMOutOfMemoryError: Direct buffer memory)。

核心總結

區域存儲內容異常類型線程共享性
程序計數器指令地址私有
虛擬機棧棧幀(局部變量/操作棧等)StackOverflowError / OOM私有
本地方法棧Native方法棧幀StackOverflowError / OOM私有
對象實例、數組OOM共享
方法區(元空間)類元數據、常量池、靜態變量OOM共享
運行時常量池字面量、符號引用OOM共享
直接內存NIO緩沖數據OOM(堆外)共享

關鍵點

  • 線程私有區(PC/棧)隨線程生滅,無需GC。
  • 共享區(堆/方法區)是GC主戰場,需關注內存溢出。
  • 直接內存不受JVM堆限制,但影響系統內存穩定性。

二、對象的創建

在HotSpot虛擬機中,對象的創建過程可概括為以下關鍵步驟:

1. 類加載檢查

  • 觸發條件:遇到new字節碼指令。
  • 檢查內容
    • 常量池中是否存在該類的符號引用
    • 類是否已被加載、解析、初始化
  • 未加載時:先執行類加載過程(詳見第7章)。

2. 內存分配

  • 分配方式(由堆內存是否規整決定):
    • 指針碰撞(Bump The Pointer):
      • 適用場景:堆內存規整(如Serial、ParNew等帶壓縮功能的收集器)。
      • 操作:移動分界指針,劃出與對象大小相等的空間。
    • 空閑列表(Free List):
      • 適用場景:堆內存不規整(如CMS基于清除算法的收集器)。
      • 操作:從空閑內存塊列表中找到足夠大的空間分配。
  • 并發處理
    • CAS+失敗重試:同步保證分配原子性。
    • TLAB(Thread Local Allocation Buffer):
      • 為每個線程預分配私有內存緩沖區,避免競爭。
      • 緩沖區用盡時,再同步申請新緩沖區。

3. 初始化零值

  • 將分配的內存空間(除對象頭)初始化為零值(0、false、null等)。
  • 目的:確保字段不賦初值可直接使用(如int默認為0)。
  • TLAB優化:分配緩沖區時同步完成初始化。

4. 設置對象頭

  • 存儲對象關鍵信息:
    • Mark Word:哈希碼(延遲計算)、GC分代年齡、鎖狀態標志等。
    • 類型指針:指向方法區的類元數據(確定對象所屬類)。
    • 數組長度(若為數組對象)。
  • :鎖狀態等信息根據虛擬機狀態動態設置(如是否啟用偏向鎖)。

5. 執行構造函數(<init>

  • 從虛擬機視角看,對象已生成;但從程序視角,對象尚未初始化。
  • 調用構造函數
    • 按程序員邏輯初始化字段(賦予實際值)。
    • 執行對象構造代碼塊(如{}或靜態塊)。
  • 完成標志:真正可用的對象被完全構造。

關鍵流程圖

new指令 → 類加載檢查 → 內存分配(指針碰撞/空閑列表) → 初始化零值 → 設置對象頭 → 執行構造函數 → 可用對象

核心特點

  • 高頻操作:對象創建極頻繁,需高效處理(如TLAB避免鎖競爭)。
  • 并發安全:通過CAS或TLAB解決多線程分配沖突。
  • 空間優化:零值初始化減少冗余賦值,提升效率。

這一過程平衡了性能(內存分配效率)、安全(并發控制)和規范(JVM語義一致性)。

三、對象的內存布局

在HotSpot虛擬機中,對象在堆內存中的存儲布局可分為三個部分:

1. 對象頭(Header)

  • Mark Word(標記字段):
    • 存儲對象自身的運行時數據:哈希碼(HashCode)、GC分代年齡、鎖狀態標志(如偏向鎖、輕量級鎖)、線程持有的鎖、偏向線程ID、偏向時間戳等。
    • 特點:長度隨虛擬機位數變化(32位系統占4字節,64位系統占8字節),為節省空間會按對象狀態復用存儲位(如未鎖定狀態下存哈希碼,加鎖后存鎖指針)。
  • 類型指針(Class Pointer):
    • 指向方法區中對象的類型元數據(Class元信息),用于確定對象屬于哪個類。
    • 例外:如果是數組對象,還需額外存儲數組長度(4字節)。

2. 實例數據(Instance Data)

  • 對象實際存儲的有效信息,即代碼中定義的字段內容(包括父類繼承的字段)。
  • 存儲規則
    • 字段順序受虛擬機分配策略參數(-XX:FieldsAllocationStyle)和源碼定義順序影響。
    • 默認策略:相同寬度的字段分配在一起(如long/doubleintshort/charbyte/boolean引用類型)。
    • 子類字段可能在父類字段的空隙中插入(通過-XX:CompactFields控制,默認開啟)。

3. 對齊填充(Padding)

  • 非必需部分,僅用于占位。
  • 作用:確保對象起始地址是8字節的整數倍(HotSpot內存管理的要求),提高內存訪問效率。
  • 觸發條件:當對象頭+實例數據總大小不是8字節倍數時,自動填充補齊。

內存布局示例

以64位系統下的普通對象為例:

|------------------------|-----------------------|
|      Mark Word (8B)    |   Class Pointer (4B)  |  → 對象頭(12B)
|------------------------|-----------------------|
|       int a (4B)       |       short b (2B)    |  → 實例數據(6B)
|------------------------|-----------------------|
|     (對齊填充 2B)       |                       |  → 填充至總大小20B(8的倍數)
|------------------------|-----------------------|

說明:實際占用18B,但需填充至24B(8字節對齊),具體對齊規則由虛擬機實現決定。


關鍵總結

部分內容作用
對象頭Mark Word + 類型指針(+數組長度)存儲運行時元數據、鎖信息、類元數據指針
實例數據對象字段值存儲對象實際有效信息
對齊填充空白字節滿足內存對齊要求,提升訪問性能

這種結構設計平衡了空間效率(如字段重排減少空隙)和訪問性能(如內存對齊優化CPU讀取速度)。

三、對象的訪問定位

在Java虛擬機中,對象訪問定位是指通過棧上的引用(reference)訪問堆中對象實例的方式。主要有兩種實現方式:

1. 句柄訪問

  • 機制:在Java堆中劃分一塊內存作為句柄池,引用存儲的是對象的句柄地址。句柄包含兩部分:
    • 指向對象實例數據的指針(堆中)
    • 指向對象類型數據的指針(方法區)
  • 優點:對象移動時(如GC整理內存),只需更新句柄中的實例數據指針,引用本身無需修改。
  • 缺點:訪問對象需兩次指針跳轉(引用→句柄→實例數據),效率較低。

2. 直接指針訪問

  • 機制:引用直接存儲對象地址,對象內存布局需額外存儲類型數據的指針(如對象頭中的類型指針)。
  • 優點:只需一次指針跳轉,訪問速度更快(無句柄中間層)。
  • 缺點:對象移動時需更新所有引用(如GC需修正指針)。


HotSpot虛擬機的選擇

  • 默認策略:使用直接指針訪問(如Serial、Parallel Scavenge等收集器),因對象訪問頻繁,減少一次指針定位可顯著提升性能。
  • 例外:Shenandoah收集器采用轉發指針(Brooks Pointer),在對象頭添加額外指針,支持并發移動對象時通過自愈(Self-Healing)機制更新引用。

?核心總結

訪問方式性能對象移動穩定性實現復雜度
句柄訪問較慢(兩次跳轉)高(引用不變)簡單
直接指針(一次跳轉)低(需更新引用)需額外設計

HotSpot優先選擇直接指針,在速度與內存布局設計間取得平衡;而Shenandoah等收集器通過轉發指針優化并發場景。

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

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

相關文章

位圖入門算法191. 位1的個數

題目鏈接&#xff1a; 191. 位1的個數 - 力扣&#xff08;LeetCode&#xff09; 這道題讓我們找出一個數字中二進制中1的個數&#xff0c;這個題目我們就用1的&來解決&#xff0c;最后一位有0為0&#xff0c;都是1才是1&#xff0c;我們只需要判斷32次即可。 代碼如下&am…

[架構之美]虛擬機Ubuntu密碼重置

[架構之美]虛擬機Ubuntu密碼重置 當您在虛擬機中運行Ubuntu系統時&#xff0c;忘記密碼不再意味著數據丟失&#xff01;本文將詳細介紹可靠的密碼重置方法&#xff0c;幫助您快速恢復系統訪問權限。 一、虛擬機密碼重置原理與準備 1.1 為什么虛擬機重置密碼更容易 在虛擬機環…

kotlin中withContext,async,launch幾種異步的區別

在 Kotlin 協程中&#xff0c;withContext、async 和 launch 是常用的異步/并發操作函數&#xff0c;它們的主要區別在于用途和返回值&#xff1a;1. launch 作用&#xff1a;啟動一個新的協程&#xff0c;用于執行不返回結果的并發任務。使用場景&#xff1a;適合執行沒有返回…

git 報錯fatal: refusing to merge unrelated histories

解決方案在你操作命令后面加--allow-unrelated-histories 例如&#xff1a; git merge master --allow-unrelated-historiesgit pull或者git push報fatal: refusing to merge unrelated histories 同理&#xff1a; git pull origin master --allow-unrelated-histories

Android 13----在framworks層映射一個物理按鍵

基于Android 13.一、映射步驟確定要映射的物理按鍵值在kl文件中增加鍵值對在InputEventLabels.cpp增加AKEYCODE在keycodes.h中定義AKEYCODE值attrs.xml中增加KEYCODEKeyEvent.java中增加KEYCODE在PhoneManagerWindow等相關類中進行攔截處理相關KEYCODE&#xff0c;屬于具體的業…

【Java EE】Mybatis-Plus

1. 開始先進行和以前一樣的項目配置、數據庫連接配置&#xff0c;在這些基礎上&#xff0c;額外引入 Mybatis-Plus 依賴即可。<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><vers…

各版本操作系統對.NET支持情況(250707更新)

借助虛擬機和測試機&#xff0c;檢測各版本操作系統對.NET的支持情況。 安裝操作系統后&#xff0c;安裝相應運行時并能夠運行星塵代理或幸運四葉草為通過條件。 測試平臺&#xff1a;VMware Workstation 鏡像來源&#xff1a;MSDN I Tell You 參考&#xff1a; .NET Fram…

5-Kafka-replication(副本機制)概念

&#x1f504; Kafka 副本機制&#xff08;Replication&#xff09; 核心概念概念說明Replica (副本)分區的完整拷貝&#xff0c;分布在不同 BrokerReplication Factor副本總數&#xff08;含 Leader&#xff09;&#xff0c;生產環境建議 ≥3Leader Replica處理所有讀寫請求&a…

langgraph的ReAct應用

一、什么是langgraph的ReActLangGraph 中的 ReAct&#xff08;Reasoning Acting&#xff09;代理是一種結合推理與行動能力的 AI 代理架構&#xff0c;通過動態決策鏈實現復雜任務處理。以下是其核心要點及實踐指南。1、ReAct 代理的核心原理1.1工作流程&#xff1a;ReAct 代理…

一個編輯功能所引發的一場知識探索學習之旅(JavaScript、HTML)

文章目錄一個編輯功能所引發的一場知識探索學習之旅&#xff08;JavaScript、HTML&#xff09;1. 一個編輯功能案例2. 知識點探索學習3. 參考資料一個編輯功能所引發的一場知識探索學習之旅&#xff08;JavaScript、HTML&#xff09; 1. 一個編輯功能案例 HTML&#xff1a; &l…

kali制作Windows木馬

環境描述&#xff1a;攻擊機&#xff1a;Kali-2025實驗靶機&#xff1a;Windows11不要攻擊他人&#xff0c;這只是網絡安全實驗還是一樣獲取IP地址制作好之后開服務&#xff0c;上傳下載在靶機右鍵保留下載記得把防火墻&#xff0c;安全中心關了否則無法下載之后就可以kali控制…

從零實現一個GPT 【React + Express】--- 【1】初始化前后端項目,實現模型接入+SSE

摘要 本系列文章主要是實現一個能夠對話以及具有文生圖等功能的模型應用。主要UI界面會參考chat-gpt,豆包等系列應用。模型使用的是gpt開源的大模型。 如果你是一個前端開發工程師需要一個自己的開源項目&#xff0c;可以學習這個系列的文章&#xff0c;不需要有很完整的后端…

【PTA數據結構 | C語言版】在順序表 list 的第 i 個位置上插入元素 x

本專欄持續輸出數據結構題目集&#xff0c;歡迎訂閱。 文章目錄題目代碼題目 請編寫程序&#xff0c;將 n 個整數存入順序表&#xff0c;對任一給定整數 x&#xff0c;將其插入順序表中指定的第 i 個位置。注意&#xff1a;i 代表位序&#xff0c;從 1 開始&#xff0c;不是數…

汽車智能化2.0引爆「萬億蛋糕」,誰在改寫游戲規則?

進入2025年&#xff0c;長安、奇瑞、比亞迪等各大主機廠紛紛將智能化推進至全新高度&#xff0c;中國汽車智能化競爭進入了“技術市場生態”綜合較量階段。一方面&#xff0c;各大主機廠全力推進輔助駕駛的規模化普及&#xff0c;掀起了一場關于高階輔助駕駛的“技術平權”革命…

QT 第八講 --- 控件篇 Widget(三)界面系列

前言&#xff1a; 在上一講《QT 第七講 --- 控件篇 &#xff08;二&#xff09;window系列與qrc機制》中&#xff0c;我們探討了應用程序窗口&#xff08;QMainWindow, QWidget&#xff09;的基礎結構、窗口標志、狀態以及Qt強大的資源管理機制&#xff08;.qrc文件&#xff0…

廣州華銳互動:AR 領域的創新與服務先鋒?

&#xff08;一&#xff09;定制化服務? 廣州華銳互動秉持 “以客戶為中心” 理念&#xff0c;為客戶提供高度定制化 AR 解決方案。項目初期&#xff0c;通過多種方式深入了解客戶需求&#xff0c;挖掘痛點。基于需求分析&#xff0c;技術團隊運用自主研發技術和先進算法&…

暑假算法日記第一天

目標?&#xff1a;刷完靈神專題訓練算法題單 階段目標&#x1f4cc;&#xff1a;【算法題單】滑動窗口與雙指針 LeetCode題目:1456. 定長子串中元音的最大數目643. 子數組最大平均數 I1343. 大小為 K 且平均值大于等于閾值的子數組數目2090. 半徑為 k 的子數組平均值2379. 得…

【軟考高項】信息系統項目管理師-第1章 信息化發展(1.5 數字化轉型與元宇宙、1.6 標題類知識點、1.7 十四五規劃內容匯總)

文章大綱 第1章 信息化發展1.5 數字化轉型與元宇宙1.5.1 數字化轉型1.5.2 元宇宙1.6 標題類知識點1.7 十四五規劃內容匯總1.8 10道試題第1章 信息化發展 學習建議: 此章內容大部分為新增內容,基本是全新的章節2023年5月考試2分選擇,5分案例2023年下半年各批次選擇題2分左右1.…

STM32F103C8T6單片機內部執行原理及啟動流程詳解

引言&#xff1a;為什么深入理解STM32啟動流程很重要&#xff1f;STM32F103C8T6作為嵌入式開發中最常用的單片機之一&#xff0c;其內部執行原理和啟動流程是理解嵌入式系統底層運行機制的核心。無論是開發Bootloader、調試HardFault異常&#xff0c;還是優化系統啟動速度&…

【python 常用的數學科學/計算機視覺等工具】

當然有&#xff01;在科學計算、機器學習、圖像處理等領域&#xff0c;scikit-learn、scikit-image&#xff08;skimage&#xff09;、SciPy、OpenCV 是非常重要的庫&#xff0c;但它們不是唯一的。以下是一些與它們類似或互補的項目&#xff0c;按照用途分類列出&#xff1a; …