首先,記憶體模型圖,如下: 其次,一句話概括各個區域的作用: 1:程式計數器(Program Counter Register),讓虛擬機中的位元組碼解釋器通過改變計數器的值來獲取下一條代碼指令,比如分支、迴圈、跳轉、異常處理、線程恢復等; 2:Java 虛擬機棧(Java Virtual Machin... ...
首先,記憶體模型圖,如下:
其次,一句話概括各個區域的作用:
1:程式計數器(Program Counter Register),讓虛擬機中的位元組碼解釋器通過改變計數器的值來獲取下一條代碼指令,比如分支、迴圈、跳轉、異常處理、線程恢復等;
2:Java 虛擬機棧(Java Virtual Machine Stacks),棧頂存放當前方法,裡面有局部變數表,
3:本地方法棧(Native Method Stacks),本地方法棧則,是為虛擬機使用到的Native 方法服務,作用同虛擬機棧。
4:Java 堆(Java Heap)是Java 虛擬機所管理的記憶體中最大的一塊,是被所有線程共用的一塊記憶體區域。此記憶體區域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這裡分配記憶體。
5:方法區(Method Area)與Java 堆一樣,是各個線程共用的記憶體區域,它用於存儲已被虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據。
Object obj = new Object();
假設這句代碼出現在方法體中,那:
1:首先包含這個方法體的類首先被載入到方法區中;
2:其次方法體本身被壓棧進虛擬機棧;
3:“Object obj”這部分的語義將會反映到虛擬機棧的本地變數表中,作為一個reference 類型數據出現。
4:而“new Object()”這部分的語義將會反映到Java 堆中,形成一塊存儲了Object 類型所有實例數據值(Instance Data,對象中各個實例欄位的數據)的結構化記憶體,這塊記憶體的地址存儲在虛擬機棧。另外,在Java 堆中還必須包含能查找到此對象類型數據(如對象類型、父類、實現的介面、方法等)的地址信息,這些類型數據則存儲在方法區中。
以上過程,用一個更具體的例子,就是如下:
附件:關於虛擬機棧訪問堆中的數據,有兩種方式,如下:
由於reference 類型在Java 虛擬機規範裡面只規定了一個指向對象的引用,並沒有定義這個引用應該通過哪種方式去定位,以及訪問到Java 堆中的對象的具體位置,因此不同虛擬機實現的對象訪問方式會有所不同,主流的訪問方式有兩種:使用句柄和直接指針。
如果使用句柄訪問方式,Java 堆中將會劃分出一塊記憶體來作為句柄池,reference中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據和類型數據各自的具體地址信息,如下圖所示。
如果使用直接指針訪問方式,Java 堆對象的佈局中就必須考慮如何放置訪問類型數據的相關信息,reference 中直接存儲的就是對象地址,如下圖所示