Java中的內(nèi)存區(qū)域(堆、棧、方法區(qū)等)分別存儲什么詳解
前言
Java虛擬機(jī)(JVM)內(nèi)存區(qū)域根據(jù)線程共享和線程私有的特性進(jìn)行劃分,主要包含 堆、虛擬機(jī)棧、本地方法棧、方法區(qū)、程序計(jì)數(shù)器 五個核心區(qū)域。以下從存儲內(nèi)容、生命周期、異常機(jī)制、結(jié)構(gòu)設(shè)計(jì)等多角度展開分析:
一、堆(Heap)
存儲內(nèi)容
- 對象實(shí)例:所有通過
new
關(guān)鍵字創(chuàng)建的對象和數(shù)組均存儲在堆中,包括成員變量、實(shí)例對象和數(shù)組元素。 - 內(nèi)存結(jié)構(gòu):堆劃分為 新生代(Eden、Survivor區(qū)) 和 老年代。新生代存放短期存活對象,老年代存放長期存活對象。
- 垃圾回收:是垃圾收集器(GC)管理的核心區(qū)域,采用分代回收算法(如標(biāo)記-清除、復(fù)制算法)。
特性與注意事項(xiàng)
- 線程共享:所有線程共享堆內(nèi)存,需考慮同步問題。
- 動態(tài)擴(kuò)展:堆大小可通過
-Xmx
(最大堆內(nèi)存)和-Xms
(初始堆內(nèi)存)參數(shù)調(diào)整。 - 異常:內(nèi)存不足時拋出
OutOfMemoryError
,常見于對象過多或內(nèi)存泄漏。
示例結(jié)構(gòu)
堆內(nèi)存結(jié)構(gòu)
├─ 新生代(Young Generation)
│ ├─ Eden Space(新對象分配區(qū))
│ ├─ Survivor From(存活對象臨時區(qū))
│ └─ Survivor To(存活對象過渡區(qū))
└─ 老年代(Old Generation)(長期存活對象)
二、虛擬機(jī)棧(Java Virtual Machine Stack)
存儲內(nèi)容
- 棧幀(Stack Frame) :每個方法調(diào)用對應(yīng)一個棧幀,包含以下數(shù)據(jù):
- 局部變量表:存儲基本數(shù)據(jù)類型(如
int
、boolean
)和對象引用(指向堆內(nèi)存地址)。 - 操作數(shù)棧:保存計(jì)算中間結(jié)果(如算術(shù)運(yùn)算的操作數(shù))。
- 動態(tài)鏈接:指向方法區(qū)中方法的符號引用。
- 方法出口:記錄方法返回地址(如
return
后的下一條指令)。
- 局部變量表:存儲基本數(shù)據(jù)類型(如
特性與注意事項(xiàng)
- 線程私有:每個線程獨(dú)立分配棧內(nèi)存,生命周期與線程一致。
- 自動釋放:方法執(zhí)行完畢后,棧幀自動出棧,無需垃圾回收。
- 異常:棧深度超過限制時拋出
StackOverflowError
,常見于無限遞歸或過深方法調(diào)用。
參數(shù)調(diào)整
- 棧大小可通過
-Xss
參數(shù)設(shè)置(如-Xss256k
),但過大會減少可創(chuàng)建的線程數(shù)。
三、方法區(qū)(Method Area)
存儲內(nèi)容
- 類元數(shù)據(jù):類的全限定名、父類名、修飾符(如
public
)、接口列表。 - 運(yùn)行時常量池:包含字面量(如字符串常量)和符號引用(如類、方法的引用)。
- 靜態(tài)變量:類級別的
static
變量。 - 即時編譯代碼:JIT(Just-In-Time)編譯器生成的本地機(jī)器代碼。
實(shí)現(xiàn)演變
- Java 8前:通過永久代(PermGen)實(shí)現(xiàn),易導(dǎo)致內(nèi)存溢出。
- Java 8后:改用元空間(Metaspace),內(nèi)存由本地內(nèi)存直接管理,減少OOM風(fēng)險。
特性與異常
- 線程共享:與堆同為共享區(qū)域。
- 動態(tài)擴(kuò)展:元空間默認(rèn)無固定上限,可通過
-XX:MaxMetaspaceSize
限制。 - 異常:內(nèi)存不足時拋出
OutOfMemoryError
,常見于加載過多類或常量池過大。
四、程序計(jì)數(shù)器(Program Counter Register)
存儲內(nèi)容
- 字節(jié)碼指令地址:記錄當(dāng)前線程執(zhí)行到的字節(jié)碼行號,用于分支、循環(huán)、異常處理等流程控制。
- Native方法標(biāo)記:若執(zhí)行本地方法(如JNI調(diào)用),計(jì)數(shù)器值為
undefined
。
特性與作用
- 線程私有:每個線程獨(dú)立維護(hù),避免多線程切換時指令混亂。
- 無內(nèi)存溢出:唯一無
OutOfMemoryError
的區(qū)域,內(nèi)存占用極小。
五、本地方法棧(Native Method Stack)
存儲內(nèi)容
- 本地方法棧幀:存儲Native方法(如C/C++編寫的JNI方法)的局部變量、參數(shù)和返回地址。
特性與異常
- 線程私有:與虛擬機(jī)棧類似,但服務(wù)于本地方法。
- 異常:棧溢出時拋出
StackOverflowError
,擴(kuò)展失敗時拋出OutOfMemoryError
。
與虛擬機(jī)棧區(qū)別
- 目標(biāo)方法:虛擬機(jī)棧服務(wù)于Java方法,本地方法棧處理非Java代碼調(diào)用。
總結(jié)對比表
內(nèi)存區(qū)域 | 存儲內(nèi)容 | 線程屬性 | 生命周期 | 異常類型 | 垃圾回收 |
---|---|---|---|---|---|
堆 | 對象實(shí)例、數(shù)組 | 共享 | 隨JVM啟動/關(guān)閉 | OutOfMemoryError | 是 |
虛擬機(jī)棧 | 局部變量、棧幀 | 私有 | 隨線程創(chuàng)建/銷毀 | StackOverflowError | 否 |
方法區(qū) | 類信息、常量、靜態(tài)變量 | 共享 | 隨JVM啟動/關(guān)閉 | OutOfMemoryError | 是(部分) |
程序計(jì)數(shù)器 | 字節(jié)碼指令地址 | 私有 | 隨線程創(chuàng)建/銷毀 | 無 | 否 |
本地方法棧 | Native方法參數(shù)、局部變量 | 私有 | 隨線程創(chuàng)建/銷毀 | StackOverflowError | 否 |
擴(kuò)展說明
直接內(nèi)存(Direct Memory)
非JVM管理區(qū)域,通過ByteBuffer.allocateDirect()
分配,避免堆內(nèi)外數(shù)據(jù)復(fù)制,常用于NIO高性能場景。其大小不受-Xmx
限制,但可能導(dǎo)致物理內(nèi)存耗盡。元空間優(yōu)化
Java 8后元空間使用本地內(nèi)存,需監(jiān)控其增長(如通過jstat -gc
),避免因動態(tài)類加載導(dǎo)致內(nèi)存泄漏。內(nèi)存異常排查
- 堆OOM:使用
jmap
生成堆轉(zhuǎn)儲文件,通過MAT(Memory Analyzer)分析對象引用鏈。 - 棧溢出:檢查遞歸調(diào)用或過深方法嵌套,優(yōu)化代碼邏輯。
- 堆OOM:使用
通過深入理解各內(nèi)存區(qū)域的存儲機(jī)制,開發(fā)者可以更精準(zhǔn)地優(yōu)化程序性能,規(guī)避潛在內(nèi)存問題。
到此這篇關(guān)于Java中的內(nèi)存區(qū)域(堆、棧、方法區(qū)等)分別存儲什么的文章就介紹到這了,更多相關(guān)Java內(nèi)存區(qū)域存儲內(nèi)容內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis的映射xml中動態(tài)設(shè)置orderby方式
這篇文章主要介紹了mybatis的映射xml中動態(tài)設(shè)置orderby方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Java后端SSM框架圖片上傳功能實(shí)現(xiàn)方法解析
這篇文章主要介紹了Java后端SSM框架圖片上傳功能實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06Java中綴表達(dá)式轉(zhuǎn)后綴表達(dá)式實(shí)現(xiàn)方法詳解
這篇文章主要介紹了Java中綴表達(dá)式轉(zhuǎn)后綴表達(dá)式實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Java中綴表達(dá)式轉(zhuǎn)換成后綴表達(dá)式的相關(guān)算法原理與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-03-03java 異常被catch后 將會繼續(xù)執(zhí)行的操作
這篇文章主要介紹了java 異常被catch后 將會繼續(xù)執(zhí)行的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02SpringBoot單元測試沒有執(zhí)行的按鈕問題及解決
這篇文章主要介紹了SpringBoot單元測試沒有執(zhí)行的按鈕問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01