首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 程序運行時數據存儲區域詳解:堆、棧、方法區、常量池

     編輯:Java 綜合教學

Java 程序運行時數據存儲區域詳解:堆、棧、方法區、常量池

Java 虛擬機在運行時將內存劃分為若干區域,每個區域有特定用途與生命週期。理解這些區域對排查 OOM、優化性能、理解對象生命週期至關重要。

運行時數據區域概覽(JDK 8+)

區域線程共享性主要內容異常
堆共享幾乎所有對象實例、數組OutOfMemoryError: Java heap space
虛擬機棧私有棧幀(局部變量表、操作數棧、動態鏈接、返回地址)StackOverflowError / OOM
本地方法棧私有Native 方法調用StackOverflowError / OOM
方法區共享類信息、常量、靜態變量、即時編譯代碼OOM: Metaspace
運行時常量池共享類文件常量池內容、符號引用、字符串常量OOM
程序計數器私有當前執行字節碼行號無

重點區域深度解析

1. 堆 - 對象實例的主戰場

  • 所有 new 的對象、數組在堆分配
  • GC 主要工作區域(分代:新生代 Eden/S0/S1、老年代)
  • -Xms/-Xmx 控制大小

2. 虛擬機棧 - 方法執行的內存模型

  • 每個方法調用創建一棧幀,存儲:局部變量表(基本類型、引用)、操作數棧、動態鏈接、返回地址
  • 局部變量表以 Slot 為單位,long/double 佔 2 Slot
  • -Xss 控制棧大小,深度遞歸易致 StackOverflowError

3. 方法區 / Metaspace - 類元數據存儲

  • JDK 8 移除永久代,改用本地內存實現 Metaspace
  • 存儲:類結構信息、運行時常量池、靜態變量、JIT 編譯代碼
  • -XX:MetaspaceSize/-XX:MaxMetaspaceSize 控制

4. 運行時常量池 - 符號引用與字符串駐留

  • 每個類一個運行時常量池,屬於方法區一部分
  • String.intern() 將字符串放入常量池(JDK 7+ 在堆中)
  • Class 文件常量池(編譯期) → 運行時常量池(加載時)

5. 直接內存 - NIO 零拷貝利器

  • 非 JVM 運行時數據區,但常被使用
  • DirectByteBuffer 通過 Native 分配堆外內存,避免堆內外拷貝
  • 受限於 -XX:MaxDirectMemorySize 與物理內存

對象創建內存分配流程

  1. 類加載檢查 → 解析符號引用
  2. 堆中劃分內存(指針碰撸/空閒列表)
  3. 初始化零值 → 設置對象頭(哈希碼、GC 信息、鎖狀態、類指針)
  4. 執行 <init> 方法(字段賦值、構造器)
  5. 返回引用給棧幀局部變量表

常見誤區澄清

  • 「基本類型在棧,引用類型在堆」不準確:基本類型作為局部變量在棧,作為對象字段在堆
  • 字符串常量池 JDK 7 起移至堆,非方法區
  • 方法區是規範,Metaspace/PermGen 是實現

掌握內存區域分佈,是 JVM 調優與故障診斷的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved