上圖是Java運行時數據區的邏輯圖,之因此說是邏輯圖,那是由於虛擬機規範只是描述虛擬機包含方法區、堆、Java棧、PC寄存器、本地方法棧,實現者只要實現虛擬機的功能便可,由於虛擬機規範沒有明確指定這幾個數據區的從屬和包含關係。數組
關於堆的描述,咱們直接引用虛擬機規範《The Java® Virtual Machine Specification Java SE 8 Edition》2015-02-13版本,2.5.4節多線程
「The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in an operating system process. It stores per-class structures such as the run-time constant pool,field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.」併發
方法區共享於Java線程。方法區用於存儲:類的結構、運行時常量池、字段、方法數據、構造方法和普通方法的字節碼內容、特殊方法。spa
方法區的類結構、字段等信息在,在類型加載時獲得,並存儲到到方法區的。雖然方法區共享於Java線程,但類加載階段只能是單線程進行,因此在類加載階段不存在併發的狀況。因爲類的靜態變動也存儲在方法內,因此類的靜態變量在使用過程當中是須要注意共享的問題的。線程
方法區也存在也須要進行內存管理(即垃圾回收),由實現虛擬者選擇具體的技術。方法區是一個邏輯區,因此方法區能夠是獨立於堆的內存,也能夠是堆中劃分出來的一部分,這個最決於虛擬機實現者具體實現和版本。指針
常量池就是該類型的直接常量和其它類型的字段、方法的符號引用。虛擬機必須爲每一個被加載的類型維護一個常量池。常量池也屬於方法區的中一部份內容。code
關於堆的描述,咱們直接引用虛擬機規範《The Java® Virtual Machine Specification Java SE 8 Edition》2015-02-13版本,2.5.3節對象
「The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.」內存
首先,Heap共享於全部Java線程,而後用於分配類實例和數組內存。通俗點解釋就是:一個Java虛擬機實例只有一個堆,用於存儲類實例和數組,而且堆是線程共享的。這就很好解釋了多線程共享堆數據要經過使用同步規則控制的緣由了。ci
「Heap storage for objects is reclaimed by an automatic storage management system (known as a garbage collector);」
規範明確虛擬機的實現要一套自動管理系統管理存儲的對象,即垃圾回收機制。但Java虛擬機並指明具體使用那些技術去管理對象的回收,虛擬機的實現者可使用任意技術進行回收。甚至極端狀況下,能夠不釋放所持有的對象,直接拋異常,由於這也是一種對象管理方式。
Java線程棧的描述,咱們直接引用虛擬機規範《The Java® Virtual Machine Specification Java SE 8 Edition》2015-02-13版本,2.5.2節
「Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.」
Java線程棧從線程建立時存在,而且是私有的。線程棧用戶存儲棧幀,棧幀用於存儲局部變量、中間運算結果。因此局部是不存在併發的問題,由於每一個棧是私有的。
Java線程棧屬於一個邏輯棧,和方法區同樣,由虛擬機的實現決定棧的位置,多是堆的一部分,也多是單獨棧區。
虛擬機只會對Java棧進行二種操做:以棧幀爲單位的壓棧和出棧。棧幀由:局部變量區、操做數棧、幀數據區。
每一條Java虛擬機線程都有本身的PC寄存器。若是這個方法不是本地方法的,那PC寄存器就保存Java虛擬機正在執行的指令的地址,若是該方法是本地的,那PC寄存器的值是undefined。PC寄存器的容量能夠存儲一個returnAddress類型的數據或者一個本地指針。
線程進入使用Java之外的語言編寫的方法,進入本地方法棧。本地方法不受虛擬機約束,能夠實現作它任何想作的事情。具體由本地方法實現決定。另外本地方法棧還能夠再回到Java方法中,再一次進入Java線程棧。
假設咱們的代碼以下圖所示,方法test調用方法add,其中方法add把兩個參數相加,並返回結果。
每當Java線程調用方法時,虛擬機就在Java線程棧中壓入一個幀,方法return或方法拋出異常時彈出棧。當線程從test方法調用add方法時,壓入add方法棧幀,則當前棧幀add幀。執行add方法後,返回結果並彈出當前幀,而後test方法的棧幀成了當前幀。