1. Java 記憶體區域與記憶體溢位異常
1.1 執行時資料區域
根據《Java 虛擬機器規範(Java SE 7 版)》規定,Java 虛擬機器所管理的記憶體如下圖所示。 java.lang.reflect.*
java.lang.util.regex.*
複製程式碼
1.1.1 程式計數器
記憶體空間小,執行緒私有。位元組碼直譯器工作是就是通過改變這個計數器的值來選取下一條需要執行指令的位元組碼指令,分支、迴圈、跳轉、異常處理、執行緒恢復等基礎功能都需要依賴計數器完成
如果執行緒正在執行一個 Java 方法,這個計數器記錄的是正在執行的虛擬機器位元組碼指令的地址;如果正在執行的是 Native 方法,這個計數器的值則為 (Undefined)。此記憶體區域是唯一一個在 Java 虛擬機器規範中沒有規定任何 OutOfMemoryError 情況的區域。
1.1.2 Java 虛擬機器棧
執行緒私有,生命週期和執行緒一致。描述的是 Java 方法執行的記憶體模型:每個方法在執行時都會床建立一個棧幀(Stack Frame)用於儲存區域性變數表、運算元棧、動態連結、方法出口等資訊。每一個方法從呼叫直至執行結束,就對應著一個棧幀從虛擬機器棧中入棧到出棧的過程。
區域性變數表:存放了編譯期可知的各種基本型別(boolean、byte、char、short、int、float、long、double)、物件引用(reference 型別)和 returnAddress 型別(指向了一條位元組碼指令的地址) StackOverflowError:執行緒請求的棧深度大於虛擬機器所允許的深度。OutOfMemoryError:如果虛擬機器棧可以動態擴充套件,而擴充套件時無法申請到足夠的記憶體。
1.1.3 本地方法棧
區別於 Java 虛擬機器棧的是,Java 虛擬機器棧為虛擬機器執行 Java 方法(也就是位元組碼)服務,而本地方法棧則為虛擬機器使用到的 Native 方法服務。也會有 StackOverflowError 和 OutOfMemoryError 異常。
1.1.4 Java 堆
對於絕大多數應用來說,這塊區域是 JVM 所管理的記憶體中最大的一塊。執行緒共享,主要是存放物件例項和陣列。內部會劃分出多個執行緒私有的分配緩衝區(Thread Local Allocation Buffer, TLAB)。可以位於物理上不連續的空間,但是邏輯上要連續。
OutOfMemoryError:如果堆中沒有記憶體完成例項分配,並且堆也無法再擴充套件時,丟擲該異常。
1.1.5 方法區
屬於共享記憶體區域,儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。
現在用一張圖來介紹每個區域儲存的內容。