這篇文章帶給大家的內容是關於Java虛擬機中記憶體管理的深入解析 ,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
方法區(Method Area)
由於Java虛擬機器的多執行緒是透過執行緒輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器都只會執行一條執行緒中的指令。因此,為了線程切換後能回復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各條線程之間計數器互不影響,獨立儲存,我們城這類內存區域為“線程私有”的內存。
如果執行緒正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機器字節碼指令的位址,如果是native方法,這個計數器值則是空。
Java虛擬機器堆疊
虛擬機棧描繪的是執行的記憶體模型:每個方法在執行的同時會建立一個堆疊幀用於儲存局部變數表,操作數棧,動態連結、方法出口等資訊。每一個方法從呼叫直到執行完成的過程,就對應一個堆疊幀在虛擬機器中入棧到出棧的過程。
一般指的堆疊就是講的虛擬機棧,或者說是虛擬機器堆疊中局部變數表部分。
局部變數表存放了編譯期可知的各種基本資料類型,物件參考和returnAddress類型(指向了一條字節碼指令的位址)。
其中long和double類型的資料會佔用兩個局部變數空間(Slot),其餘資料型別只佔一個。
局部變數表所需的記憶體空間在編譯期完成分配,當進入一個方法時,這個方法需要在幀中分配多大的局部標量空間是完全確定的,在方法運行期間不會改變局部變數表的大小。
虛擬機器規範中對這個區域規定了兩種異常狀況:如果執行緒請求的堆疊深度大於虛擬機器所允許的深度,將拋出StackOverflowError異常;如果虛擬機器堆疊可以動態擴展,如果擴展時無法申請到足夠的內存,就會拋出OutOfMemoryError異常。
本地方法堆疊
Java堆
堆是所有執行緒共享的一塊記憶體區域,在虛擬機器啟動時創建。此記憶體區域的唯一目的是存放物件實例,幾乎所有物件實例都是在這裡分配記憶體(所有物件實例和陣列)。
Java堆是垃圾收集器管理的主要區域。因現收集器基本上都採用分帶收集方法,所以Java堆中還可以細分為:新生代和老生代。
從記憶體分配的角度,在執行緒共享的Java堆中可能會分割出多個執行緒私有的分配緩衝區(Thread Local Allocation Buffer, TLAB)。
Java堆可以處理物理上不連續的記憶體空間,只要邏輯上是連續的即可。在實現時,可以實現成固定大小的,也可以可拓展的,不過主流的虛擬機都是按可拓展實現(-Xms、-Xmx控制)。
方法區
除了和Java堆一樣不需要連續的記憶體和可以選擇固定大小或可拓展外,還可以選擇不實現垃圾回收。垃圾回收在這個區域內很少發生,但並非進入了方法區就如永生代一樣永久存在了。這個區域的記憶體回收主要是針對常量池的回收和對類型的卸載。
運行時常數池
具備動態性,並非預先置入Class文件中常量池的內容才能進入方法區運行時常量池,運行期也可能將新的常量放入池中,這種特性被開發人員利用的比較多的是String類別的intern().
虛擬機器接到一條new指令時,首先去檢查這條指令的參數是否能在常數池中定位到一個類別的符號引用,並且檢查這個符號引用代表的類別是否已經被載入、解析和初始化過。如果沒有那麼必須先執行回應的類別載入過程。
在類別載入檢查之後就為新生物件分配記憶體。物件所需記憶體大小在類別載入完成後便可完全確定。
記憶體分配完成之後,虛擬機器需要分配到的記憶體空間都初始化為零,如果使用TLAB,這項工作可以提前至TLAB分配時進行。
接下來虛擬機器對物件進行必要的設置,例如這個物件是 哪個類別的實例,如何才能找到類別的元資料資訊、物件的雜湊碼、物件的GC分代年齡等資訊。這些資訊放在物件的物件頭中。
完成上步之後,對於虛擬機器之後已經完成任務了,但從Java程式的角度來看,物件建立才剛開始,
物件內存在記憶體中的佈局可以分為3部分:物件頭、實例資料和對齊填滿。
HotSpot虛擬機的物件頭包括兩部分:
1.儲存物件本身的執行時間數據,如雜湊嗎、GC分代年齡、鎖定狀態標誌、執行緒持有鎖、偏向線程ID、偏向時間戳記等。資料長度在32位元和64位元虛擬機器分別為32bit和64bit,官方成為「Mark word」。
2.型別指針,也就是物件之鄉它的類別元資料的指針,虛擬機器透過這個指針來決定這個物件是哪個類別的實例。如果物件是一個Java數組,拿在物件頭中還必須有一塊用於記錄數組長度的數據,因為虛擬機器可以透過普通Java物件的元資料來決定Java物件大小,但從數組的元資料中卻無法確定數組的大小。
Java程式堆疊上的reference資料可以透過以下兩種主流方式存取堆疊中的物件實例。
句柄:Java堆中會分配一塊記憶體用來當句柄吃,reference儲存的就是這個物件的句柄位址。句柄中包含了物件範例資料與型別資料各自的具體體質。
直接指標:Java堆物件佈局中就必須考慮如何防止存取類型資料的相關資訊。
相關推薦:
#以上是Java虛擬機器中記憶體管理的深入解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!