Java 虛擬機 (JVM) 在執行 Java 程式的過程中,會將其管理的記憶體劃分為若干個不同的數據區域。每個區域都有其特定的用途,以及各自的創建和銷毀時間。理解這些記憶體區域的結構與特性,對於編寫高效能、穩定的 Java 應用程式,以及進行記憶體調優和故障排查至關重要。本文將系統性地梳理 JVM 運行時數據區的核心組成。
根據《Java 虛擬機規範》,JVM 所管理的記憶體包含以下幾個核心運行時數據區域:
其中,程式計數器、虛擬機棧、本地方法棧是線程私有的,隨線程啟動而創建,隨線程結束而銷毀;而堆、方法區、運行時常量池是線程共享的;直接記憶體則不屬於 JVM 運行時數據區範疇,但也可能被頻繁使用。
程式計數器可以看作是當前線程所執行的字節碼行號指示器。在 JVM 的概念模型中,字節碼解釋器的工作就是通過改變程式計數器的值來選取下一條需要執行的字節碼指令。分支、循環、跳轉、異常處理、線程恢復等基礎功能都依賴此計數器完成。
Java 虛擬機棧同樣是線程私有的,生命週期與線程相同。它描述的是 Java 方法執行的記憶體模型:每個方法在執行時都會創建一個棧幀,用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每個方法從調用至執行完成,對應一個棧幀在虛擬機棧中入棧到出棧的過程。
StackOverflowError;若擴展時無法申請到足夠記憶體,拋出 OutOfMemoryError。本地方法棧與虛擬機棧作用相似,區別在於虛擬機棧為虛擬機執行的 Java 方法服務,而本地方法棧則為虛擬機使用到的 Native 方法服務。部分虛擬機(如 HotSpot)將兩者合二為一。同樣會拋出 StackOverflowError 和 OutOfMemoryError。
Java 堆是所有線程共享的一塊記憶體區域,在虛擬機啟動時創建。此區域的唯一目的就是存放對象實例。 幾乎所有的對象實例都在這裡分配記憶體。
OutOfMemoryError。方法區是各線程共享的記憶體區域,用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。
OutOfMemoryError。是方法區的一部分,用於存放編譯期生成的各種字面量和符號引用。具有動態性,運行期間也可將新的常量放入池中(如 String.intern())。
非虛擬機運行時數據區一部分。NIO 引入基於通道與緩衝區的 I/O 方式,可使用 Native 函數庫直接分配堆外記憶體,再通過堆中的 DirectByteBuffer 對象引用操作。不受 Java 堆大小限制,但受本機記憶體限制,同樣可能導致 OutOfMemoryError。
new 指令,檢查常量池定位類符號引用,並驗證類是否已加載、解析、初始化。<init> 方法:按程序員意願初始化,對象才算真正可用。Java 程式通過棧上的 reference 數據操作堆上的對象,主流方式有兩種:
掌握 JVM 記憶體區域劃分、對象創建流程及訪問機制,是深入理解 Java 運行原理、進行性能調優與問題診斷的基石。合理規劃堆大小、選擇適合的 GC 策略、避免記憶體洩漏,皆建立在對這些核心概念的透徹理解之上。