1. 程式人生 > >Java虛擬機器原理(一)

Java虛擬機器原理(一)

Java虛擬機器記憶體模型

Java虛擬機器模型是Java程式執行的基礎。為了能使程式正常執行,JVM將記憶體資料分為程式計數器、虛擬機器棧、本地方法棧、Java堆和方法區等部分,如下圖所示。JVM記憶體模型現將各部分具體介紹如下:

1.程式計數器

程式計數器(Program Counter Register)是一塊很小的記憶體空間,用於存放下一條要執行的指令。由於Java是執行緒級別的語言,當執行緒數量超過CPU數量時,執行緒之間根據時間片輪詢搶佔CPU資源。對於單核CPU來說,每一個時刻只能有一個執行緒在執行,其他執行緒必須被切換出去。為此,每個執行緒必須用一個獨立的程式計數器記錄下一條將要執行的指令。各個執行緒之間的程式計數器獨立工作、互不影響,是一塊執行緒私有的記憶體空間。
如果當前執行緒正在執行一個Java方法,則程式計數器記錄正在執行的Java位元組碼地址;如果正在執行一個native方法,則程式計數器為空。

2.Java虛擬機器棧

Java虛擬機器棧用於存放Java函式呼叫的堆疊資訊,它也是執行緒私有的記憶體空間。Java虛擬機器棧和Java執行緒同時建立,儲存方法的區域性變數和部分結果,並參與方法的呼叫和返回。
JVM規範允許Java棧的大小是動態的或者固定的。在JVM規範中定義了兩種與棧空間相關的異常:StackOverflowErrorOutOfMemoryError。如果執行緒在計算過程中,請求棧的深度大於最大可用棧深度,則丟擲StackOverflowError;如果Java棧可以動態擴充套件,而在擴充套件棧的過程中沒有足夠的空間支援,則丟擲OutOfMemoryError

3.本地方法棧

本地方法棧和Java虛擬機器棧的功能相似,Java虛擬機器棧用於管理Java函式的呼叫,而本地方法棧用於管理native方法的呼叫。本地方法棧不是採用Java實現的,而是用C實現的。在SUN的Hot Spot中並不區分本地方法棧和虛擬機器棧。
和Java虛擬機器棧一樣,本地方法棧也會丟擲StackOverflowErrorOutOfMemoryError

4.Java堆

Java堆是Java執行時記憶體中最為重要的部分,幾乎所有的物件和陣列都是在堆中分配空間的。Java堆被所有的執行緒共享。
Java堆分為Young代和Old代兩個部分。Young代用於存放剛剛建立的物件和年輕的物件,如果物件一直沒有被回收,生存期足夠長,則會被作為老年物件進入Old代。
Young代又進一步分為Eden、Survivor0和Survivor1三個區域。Eden意義為伊甸園,大部分剛剛建立的物件都儲存在此區域。S0和S1為Survivor區域,表示倖存者,即其中的物件至少經歷過一次垃圾回收且保留了下來。如果Survivor的的物件到了指定年齡(預設為15)仍未被回收,則有機會進入Old代。
關於Java堆的具體內容將在下一節詳細闡述。

5.方法區

方法區也是JVM記憶體中非常重要的一塊區域,主要用於儲存常量和類的定義資訊。與Java堆類似,方法區也被所有執行緒共享。
方法區中最為重要資訊有:類的型別資訊、常量池、域資訊、方法資訊等。這些資訊大部分來自class位元組碼檔案,是Java程式執行必不可少的重要資料。
在Hot Spot中,方法區也被稱為永久區。雖然被稱為永久區,但是也是可以被GC回收的。關於具體的垃圾回收機制,將在後文介紹。

總結

Java虛擬機器將記憶體資料主要分為五個部分,包括:程式計數器、虛擬機器棧、本地方法棧、Java堆和方法區。程式計數器用於儲存下一條將要被執行的指令;Java虛擬機器棧和本地方法棧分別存放Java方法和native方法的呼叫資訊;Java堆儲存的程式執行時所需的物件等資料;而方法區主要用於存放類的元資料資訊。
其中,程式計數器、Java虛擬機器棧和本地方法棧是執行緒私有的, 各個執行緒獨立工作互不影響;而Java堆和方法區則被JVM中的所有執行緒共享。