深入理解 Java 虛擬機內存區域

Java 虛擬機(JVM)是 Java 程序運行的核心環境,它通過內存管理為程序提供高效的執行支持。JVM 在運行時將內存劃分為多個區域,每個區域都有特定的作用和生命周期。本文將詳細介紹 JVM 的運行時數據區域及其功能,并探討與內存相關的常見問題,如內存溢出(OOM)和棧溢出(SOF)。
在這里插入圖片描述


JVM 運行時數據區域

JVM 將其管理的內存劃分為若干區域,包括線程私有和線程共享兩類。以下是主要區域的概覽:

1. 程序計數器(Program Counter Register)

  • 作用:線程私有的小型內存區域,記錄當前線程執行的字節碼指令地址,用于控制程序流程(如分支、循環、跳轉等)。
  • 特點
    • 若執行 Java 方法,則記錄字節碼地址;若執行 Native 方法,則為空(Undefined)。
    • 是唯一不會拋出 OutOfMemoryError 的區域。
  • 生命周期:隨線程創建而生,隨線程結束而滅。

2. Java 虛擬機棧(Java Virtual Machine Stacks)

  • 作用:線程私有,管理 Java 方法的執行。每個方法調用對應一個棧幀(Stack Frame),包含局部變量表、操作數棧、動態連接和方法返回地址。
  • 棧幀結構
    • 局部變量表:存儲方法參數和局部變量。
    • 操作數棧:存放中間計算結果和臨時變量。
    • 動態連接:支持方法調用時的符號引用解析。
    • 方法返回地址:記錄方法返回位置。
  • 異常
    • 棧深度超限:StackOverflowError
    • 內存不足:OutOfMemoryError
  • 調整:通過 -Xss 參數設置棧大小。

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

  • 作用:線程私有,為 Native 方法服務,功能與虛擬機棧類似。
  • 異常:同樣可能拋出 StackOverflowErrorOutOfMemoryError

4. Java 堆(Java Heap)

  • 作用:線程共享,存儲對象實例,是垃圾收集器(GC)的主要管理區域。
  • 分代結構
    • 新生代:包括 Eden 和 Survivor(S0、S1),存放新對象。
    • 老年代:存放長期存活的對象。
    • 元空間(JDK 8 后取代永久代):使用本地內存。
  • 年齡限制:對象年齡記錄在對象頭,最大值為 15(4 位二進制),由 -XX:MaxTenuringThreshold 設置。
  • 異常:內存不足時拋出 OutOfMemoryError
  • 調整:通過 -Xms(初始值)和 -Xmx(最大值)配置堆大小。

5. 方法區(Method Area)

  • 作用:線程共享,存儲類信息、常量、靜態變量和編譯后的代碼。
  • 演變
    • JDK 7 前:稱為永久代(PermGen),通過 -XX:MaxPermSize 設置。
    • JDK 8 后:改為元空間(Metaspace),通過 -XX:MaxMetaspaceSize 設置,使用本地內存。
  • 異常:擴展失敗拋出 OutOfMemoryError

6. 運行時常量池(Runtime Constant Pool)

  • 作用:方法區的一部分,存儲 Class 文件中的字面量(如字符串常量)和符號引用。
  • 特點:具備動態性,運行時可通過 String.intern() 添加常量。
  • 異常:內存不足拋出 OutOfMemoryError

7. 直接內存(Direct Memory)

  • 作用:非 JVM 規范定義區域,通過 NIO(如 DirectByteBuffer)直接分配堆外內存。
  • 調整:通過 -XX:MaxDirectMemorySize 設置,默認與 -Xmx 一致。
  • 異常:分配失敗拋出 OutOfMemoryError

內存區域對比

區域作用范圍可能異常
程序計數器線程私有
虛擬機棧線程私有StackOverflowError, OutOfMemoryError
本地方法棧線程私有StackOverflowError, OutOfMemoryError
Java 堆線程共享OutOfMemoryError
方法區線程共享OutOfMemoryError
運行時常量池線程共享OutOfMemoryError
直接內存非運行時區OutOfMemoryError

對象在 JVM 中的生命周期

1. 對象創建

  • 步驟
    1. 遇到 new 指令,檢查常量池中類的符號引用并加載類。
    2. 在堆中分配內存(指針碰撞或空閑列表)。
    3. 初始化對象(調用 <init>() 方法)。
  • 內存分配方式
    • 指針碰撞:堆內存規整時使用。
    • 空閑列表:堆內存不規整時使用,依賴垃圾收集器是否帶壓縮功能。
  • 并發安全:通過 CAS 或 TLAB(線程本地分配緩沖)確保分配安全。

2. 對象內存布局

  • 對象頭
    • Mark Word:存儲運行時數據(如哈希碼、GC 年齡、鎖狀態)。
    • 類型指針:指向類的元數據。
    • 數組長度(僅數組對象):記錄數組大小。
  • 實例數據:存儲字段內容。
  • 對齊填充:確保內存對齊。

3. 對象訪問

  • 句柄訪問reference 指向句柄池,穩定但間接。
  • 直接指針(HotSpot 默認):reference 直接指向對象地址,速度更快。

內存溢出與棧溢出

1. OutOfMemoryError (OOM)

除程序計數器外,其他區域都可能因內存不足拋出 OOM。常見場景包括:

  • 堆溢出:對象過多,-Xmx 不足。
  • GC 開銷超限:GC 時間超 98% 且回收不足 2%。
  • 元空間不足:類加載過多。
  • 直接內存溢出:NIO 分配超限。
  • 線程創建失敗:系統內存不足以支持新線程。

2. StackOverflowError (SOF)

  • 原因
    • 遞歸過深。
    • 大量循環或死循環。
  • 參數:通過 -Xss 調整棧大小。

示例分析

以下是一個簡單程序的內存分配過程:

public class JVMCase {public final static String MAN_SEX_TYPE = "man"; // 常量池public static String WOMAN_SEX_TYPE = "woman";   // 方法區public static void main(String[] args) {Student stu = new Student(); // 堆中創建對象,棧中存引用stu.setName("nick");JVMCase jvmcase = new JVMCase();print(stu); // 靜態方法入棧jvmcase.sayHello(stu); // 非靜態方法入棧}
}
  • 類加載時,靜態變量和常量分配在方法區。
  • main 執行時,對象在堆中創建,引用存于棧中,方法調用依次入棧。

結語

理解 JVM 內存區域是掌握 Java 性能調優的基礎。從線程私有的程序計數器到共享的 Java 堆和方法區,每個區域各司其職。通過合理配置參數(如 -Xmx-Xss-XX:MaxMetaspaceSize),并結合工具(如 jmap、MAT)分析內存問題,可以有效避免 OOM 和 SOF,提升程序穩定性。

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

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

相關文章

PDF轉JPG(并去除多余的白邊)

首先&#xff0c;手動下載一個軟件&#xff08;poppler for Windows&#xff09;&#xff0c;下載地址&#xff1a;https://github.com/oschwartz10612/poppler-windows/releases/tag/v24.08.0-0 否則會出現以下錯誤&#xff1a; PDFInfoNotInstalledError: Unable to get pag…

深入剖析MyBatis緩存機制:原理、源碼與實戰指南

引言 MyBatis作為一款優秀的ORM框架,其緩存機制能顯著提升數據庫查詢性能。但許多開發者僅停留在“知道有緩存”的層面,對其實現原理和細節知之甚少。本文將結合可運行的代碼示例和源碼分析,手把手帶您徹底掌握MyBatis緩存機制。 一、MyBatis緩存分類 MyBatis提供兩級緩存…

Vue 使用 vue-router 時,多級嵌套路由緩存問題處理

Vue 使用 vue-router 時&#xff0c;多級嵌套路由緩存問題處理 對于三級菜單&#xff08;或多級嵌套路由&#xff09;&#xff0c;vue 都是 通過 keep-alive 組件來實現路由組件的緩存。 有時候三級或者多級路由時&#xff0c;會出現失效情況。以下是三級菜單緩存的例子。 最…

QSplitter保存和讀取

官方文檔提供的方案 保存 connect(ui->splitter, &QSplitter::splitterMoved, [](){settings.setValue("splitterSizes", ui->splitter->saveState()); });讀取 ui->splitter->restoreState(settings.value("splitterSizes").toByteA…

VanillaVueSvelteReactSolidAngularPreact前端框架/庫的簡要介紹及其優勢

VanillaVueSvelteReactSolidAngularPreact前端框架/庫的簡要介紹及其優勢。以下是這些前端框架/庫的簡要介紹及其優勢&#xff1a; 1. Vanilla 定義&#xff1a;Vanilla 并不是一個框架&#xff0c;而是指 原生 JavaScript&#xff08;即不使用任何框架或庫&#xff09;。優勢…

Java多線程與高并發專題——關于CopyOnWrite 容器特點

引入 在 CopyOnWriteArrayList 出現之前&#xff0c;我們已經有了 ArrayList 和 LinkedList 作為 List 的數組和鏈表的實現&#xff0c;而且也有了線程安全的 Vector 和Collections.synchronizedList() 可以使用。 首先我們來看看Vector是如何實現線程安全的 &#xff0c;還是…

Jmeter接口測試詳解

今天筆者呢&#xff0c;想給大家聊聊Jmeter接口測試流程詳解&#xff0c;廢話不多說直接進入正題。 一、jmeter簡介 Jmeter是由Apache公司開發的java開源項目&#xff0c;所以想要使用它必須基于java環境才可以&#xff1b; Jmeter采用多線程&#xff0c;允許通過多個線程并…

DeepSeek開啟AI辦公新模式,WPS/Office集成DeepSeek-R1本地大模型!

從央視到地方媒體&#xff0c;已有多家媒體機構推出AI主播&#xff0c;最近杭州文化廣播電視集團的《杭州新聞聯播》節目&#xff0c;使用AI主持人進行新聞播報&#xff0c;且做到了0失誤率&#xff0c;可見AI正在逐漸取代部分行業和一些重復性的工作&#xff0c;這一現象引發很…

通過Golang的container/list實現LRU緩存算法

文章目錄 力扣&#xff1a;146. LRU 緩存主要結構 List 和 Element常用方法1. 初始化鏈表2. 插入元素3. 刪除元素4. 遍歷鏈表5. 獲取鏈表長度使用場景注意事項 源代碼閱讀 在 Go 語言中&#xff0c;container/list 包提供了一個雙向鏈表的實現。鏈表是一種常見的數據結構&#…

【大學生體質】智能 AI 旅游推薦平臺(Vue+SpringBoot3)-完整部署教程

智能 AI 旅游推薦平臺開源文檔 項目前端地址 ??項目介紹 智能 AI 旅游推薦平臺&#xff08;Intelligent AI Travel Recommendation Platform&#xff09;是一個利用 AI 模型和數據分析為用戶提供個性化旅游路線推薦、景點評分、旅游攻略分享等功能的綜合性系統。該系統融合…

【滲透測試】基于時間的盲注(Time-Based Blind SQL Injection)

發生ERROR日志告警 查看系統日志如下&#xff1a; java.lang.IllegalArgumentException: Illegal character in query at index 203: https://api.weixin.qq.com/sns/jscode2session?access_token90_Vap5zo5UTJS4jbuvneMkyS1LHwHAgrofaX8bnIfW8EHXA71IRZwsqzJam9bo1m3zRcSrb…

redis數據類型以及底層數據結構

redis數據類型以及底層數據結構 String&#xff1a;字符串類型&#xff0c;底層就是動態字符串&#xff0c;使用sds數據結構 Map:有兩種數據結構&#xff1a;1.壓縮列表&#xff1a;當hash結構中存儲的元素個數小于了512個。并且元 …

DeepSeek R1-32B醫療大模型的完整微調實戰分析(全碼版)

DeepSeek R1-32B微調實戰指南 ├── 1. 環境準備 │ ├── 1.1 硬件配置 │ │ ├─ 全參數微調:4*A100 80GB │ │ └─ LoRA微調:單卡24GB │ ├── 1.2 軟件依賴 │ │ ├─ PyTorch 2.1.2+CUDA │ │ └─ Unsloth/ColossalAI │ └── 1.3 模…

window下的docker內使用gpu

Windows 上使用 Docker GPU需要進行一系列的配置和步驟。這是因為 Docker 在 Windows 上的運行環境與 Linux 有所不同,需要借助 WSL 2(Windows Subsystem for Linux 2)和 NVIDIA Container Toolkit 來實現 GPU 的支持。以下是詳細的流程: 一、環境準備 1.系統要求 Window…

Ubuntu 下 nginx-1.24.0 源碼分析 - cycle->modules[i]->type

Nginx 中主要有以下幾種模塊類型 類型 含義 NGX_CORE_MODULE 核心模塊&#xff08;如進程管理、錯誤日志、配置解析&#xff09;。 NGX_EVENT_MODULE 事件模塊&#xff08;如 epoll、kqueue 等 IO 多路復用機制的實現&#xff09;。 NGX_HTTP_MODULE HTTP 模塊&#xf…

八、排序算法

一些簡單的排序算法 8.1 冒泡排序 void Bubble_sort(int a[] , int len){int i,j,flag,tmp;for(i=0 ; i < len-1 ; i++){flag = 1;for(j=0 ; j < len-1-i ; j++){if(a[j] > a[j+1]){tmp = a[j];a[j] = a[j+1];a[j+1] = tmp;flag = 0;}}if(flag == 1){break;}}…

Sqlserver安全篇之_手工創建TLS用到的pfx證書文件

Sqlserver官方提供的Windows Powershell腳本 https://learn.microsoft.com/zh-cn/sql/database-engine/configure-windows/configure-sql-server-encryption?viewsql-server-ver16 # Define parameters $certificateParams {Type "SSLServerAuthentication"Subje…

npm install -g @vue/cli 方式已經無法創建VUE3項目

采用該方式&#xff0c;啟動VUE3項目&#xff0c;運行命令&#xff0c;出現報錯&#xff1a; npm install -g vue/cli PS D:\> npm install -g vue/cli npm warn deprecated inflight1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lr…

3.8[a]cv

函數核心目標 實現屏幕空間內三角形的光柵化&#xff0c;將三角形覆蓋的像素點顏色填充到幀緩沖區&#xff0c;同時處理深度測試&#xff08;Z-Buffer&#xff09;。這是渲染管線中幾何階段到像素階段的關鍵步驟 包圍盒計算&#xff08;Bounding Box&#xff09;?** ?功能&…

導入 Excel 規則批量修改或刪除 Excel 表格內容

我們前面介紹過按照規則批量修改 Excel 文檔內容的操作&#xff0c;可以對大量的 Excel 文檔按照一定的規則進行統一的修改&#xff0c;可以很好的解決我們批量修改 Excel 文檔內容的需求。但是某些場景下&#xff0c;我們批量修改 Excel 文檔內容的場景比較復雜&#xff0c;比…