標籤:
運行時資料區域:
Java虛擬機器在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域。這些地區都有各自的用途,以及建立和銷毀的時間,有的地區隨著虛擬機器進程啟動而存在,有些地區則依賴使用者線程的啟動和結束位建立和銷毀,根據《Java虛擬機器規範》,Java虛擬機器將會包含以下幾個運行時資料區域:
(圖片來源於網路)
程式計數器:
程式計數器(Progeam Counter Register)是一塊較小的記憶體空間,可以看成當前程式所執行的位元組碼的行號指標;
由於Java虛擬機器多線程是通過線程輪流切換並分配處理執行時間的方式來實現的,需要在切換後線程間的程式計數器互不影響,所以執行緒計數器是線程私人的;
如果線程正在執行的是一個Java方法,計數器記錄的是正在執行的虛擬機器位元組碼指令的地址,如果正在執行的是Native方法,計數器為空白;
此記憶體地區是唯一一個在Java虛擬機器規範中沒有規定任何OutOfMemoryError情況的地區
Java虛擬機器棧:
Java虛擬機器棧(Java Virtual Machine Stacks)也是線程私人的,它的生命週期與線程相同。虛擬機器棧描述的是Java方法執行的記憶體模型:每個方法在執行的同時會建立一個棧幀(Srack Frame)用於儲存局部變數表、運算元棧、動態連結、方法出口等資訊。每一個方法從調用直至執行完成的過程,就對應著一個棧幀在虛擬機器棧中入棧到出棧的過程。
經常我們把Java記憶體分為堆記憶體(Heap)和棧記憶體(Stack),這種分發比較粗糙的,通常是棧記憶體只是Java虛擬機器棧的局部變數部分。
局部變數表存放了編譯期可知的各種基礎資料型別 (Elementary Data Type)(boolean、byte、char、short、int、float、long、double)以及對象的引用(reference類型,可能是一個指向對象其真實位址的引用指標,也可能是指向一個代表對象的控制代碼或其他與此對象有關的位置)和returnAddress類型(指向了一個一條位元組碼指令的地址);其中64位長度的龍和double類型的資料佔用2個局部變數空間(Slot),其餘資料類型只佔1個空間。局部變數表所需記憶體給空間在編譯期分配,在方法運行期間不會改變大小。
異常:StackOverflowError當棧深度大於允許的深度時拋出;OutOfMemoryError當擴充時無法申請到足夠的記憶體時拋出
本地方法棧:
本地方法棧(Native Method Stack),與虛擬機器棧功能類似,只是,本地方法棧只用於Native方法服務,而虛擬機器棧魚魚Java方法服務。虛擬機器規範中沒有對本地方法棧中使用語言和資料結構做牆紙規定。所以存在如Sun HotSpot虛擬機器這樣直接把本地方法棧和虛擬機器棧合二為一的。
Java堆:
Java堆(Java Heap)是Java虛擬機器所管理的記憶體中最大的一塊,被所有線程共用,在虛擬機器啟動時建立
Java堆是垃圾收集器管理的主要區域,因此很多時候也被叫做“GC堆"
根據Java虛擬機器規範的規定,Java堆可以處於物理上不連續的記憶體空間中,只要邏輯上連續即可
當堆中記憶體不足,且無法再擴充時,將會拋出OutOfMemoryError異常
方法區:
方法區(Method Area)與Java堆一樣,是各個線程共用的記憶體地區,它用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的代碼等資料。
在Java虛擬機器規範中對方法區的限制非常寬鬆,除了和Java堆一樣不需要連續的記憶體和可以選擇固定大小或者可擴充外,還可以選擇不實現記憶體回收。這個地區的記憶體回收主要目標是針對常量池的回收和對類型的卸載,這個地區的記憶體回收現在還比較難令人滿意,主要是類型的卸載,條件相當的苛刻。
JDK1.7以前Sun HotSpot將GC分代手機擴充到了方法區,省去了專門為方法區編寫記憶體管理代碼的工作,但這樣更容易造成記憶體溢出,所以在JDK1.7中,HotSpot已經把原本放在永久代中的字串常量池移出。
Java虛擬機器規範規定,當無法滿足記憶體配置需求是,將拋出OutOfMemoryError異常。
運行時常量池:
運行時常量池(Runtime Constant Pool)是方法區的一部分。Class檔案中除了有雷德版本、欄位、方法、介面等描述資訊外,還有一項資訊是常量池,用於存放編譯期產生的各種字面量和符號引用,這部分內容將在類載入後進入方法區的運行時存放。
Java虛擬機器學習(二)