本文是我閱讀周志明老師《深入理解Java虛擬機-JVM高級特性與最佳實戰》章節2.2的學習筆記。更多內容,請參考原書。
Java虛擬機在執行Java程序時會將其所管理的內存劃分為若干個不同的數據區域,這些區域有各自的用途及生命周期。具體而言包括以下幾個區域。
1. 程序計數器
一塊較小的內存空間,可視作當前線程所執行的字節碼的行號指示器。主要用途是選取該線程下一條需要執行的字節碼指令。
每個線程有一個獨立的程序計數器,各個線程的計數器之間互不影響,獨立存儲。這樣的內存區域也被稱為“線程私有”的內存。
若線程在執行Java方法,則計數器記錄正在執行的虛擬機字節碼指令的地址;若正在執行Native方法,則計數器為“Undefined”。
2. 虛擬機棧
同樣是線程私有的,其生命周期與線程同步。虛擬機棧描述Java方法執行的內存模型,每個方法在執行時都會創建一個Stack Frame,其中存儲了局部變量表,操作數棧,動態鏈接,方法出口等信息。每個方法從調用到執行完成的過程,即對應著一個Stack Frame在虛擬機棧中從入棧到出棧的過程。
局部變量表存放編譯器可知的各種基本數據類型,對象引用及Return Adress類型。局部變量表所需的內存空間在編譯期間完成分配,也就是說進入一個方法時,其Stack Frame中的局部變量空間是確定的,在運行期間不會改變。
當線程請求的棧深度大於虛擬機所允許的深度,即拋出“StackOverflowError”;若虛擬機可動態擴展(當前大部分虛擬機都可擴展),若擴展時無法申請到足夠的內存,則拋出“OutOfMemoryError”。
3. 本地方法棧
主要為虛擬機使用到的Native方法服務,其作用與虛擬機棧類似。
4. Java堆
Java堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建,是虛擬機管理的內存中最大的一塊。基本來說,所有的對象實例及數組都要在這裡分配內存。某個對象分配的空間大小是另一個問題。
Java堆是垃圾收集器管理的主要區域,因此很多時候也被稱為“GC堆”(Garbage Collection Heap)。堆上各個區域的分配回收等是GC問題。
Java堆只需是邏輯上連續的即可,不必物理上連續。目前主流的虛擬機都將堆實現成了可擴展的(-Xmx,-Xms,即最大堆和初始堆大小)。若堆需要擴展而無法擴展時,也會拋出“OutOfMemory-Error”。
5. 方法區
Method Area也是被各個線程共享的內存區域,用去存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等數據。邏輯上來說屬於堆的一部分。
關於方法區,運行時常量池及直接內存等的相關內容,請參考原書。
深入理解Java虛擬機:JVM高級特性與最佳實踐 第2版 高清PDF+源碼 下載 http://www.linuxidc.com/Linux/2014-09/106869.htm