線程共享。程序員
GC堆,存放對象實例和數組(對象數組、基本類型數組)。算法
若是在堆中沒有內存完成實例分配,而且堆也沒法再擴展時,將會拋出OutOfMemoryError異常。數組
現代的垃圾收集器基本都是採用分代收集算法,其主要的思想是針對不一樣類型的對象採起不一樣的垃圾回收算法,能夠將堆分紅兩塊:oop
線程共享。佈局
存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼。線程
JDK 1.8 以前,HotSpot 虛擬機把它當成永久代來進行垃圾回收。可是很難肯定永久代的大小,由於它受到不少因素影響,而且每次 Full GC 以後永久代的大小都會改變,因此常常會拋出 OutOfMemoryError 異常。設計
爲了更容易管理方法區,從 JDK 1.8 開始,移除永久代,並把方法區移至元空間,它位於本地內存中,而不是虛擬機內存中。指針
注:HotSpot虛擬機的設計團隊選擇把GC分代收集擴展至方法區,或者說使用永久代來實現方法區(Non-Heap)。對象
運行時常量池(Runtime Constant Pool)
Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池(Constant Pool Table),用於存放編譯期生成的各類字面量(Literal,如文本字符串、 聲明爲final的常量值等)和符號引用(Symbolic References,類和接口的全限定名(Fully Qualified Name)、字段的名稱和描述符(Descriptor)、方法的名稱和描述符)[2],這部份內容將在類加載後進入方法區的運行時常量池中存放。
線程私有。
Java方法執行的內存模型:每一個 Java 方法在執行的同時會建立一個棧幀用於存儲局部變量表、操做數棧、常量池引用等信息。從方法調用直至執行完成的過程,就對應着一個棧幀在 Java 虛擬機棧中入棧和出棧的過程。局部變量表存放了編譯期可知的基本數據類型、對象引用(reference類型)、returnAddress類型。
StackOverflowError異常(若是線程請求的棧深度大於虛擬機所容許的深度),OutOfMemoryError異常(若是虛擬機棧能夠動態擴展, 擴展時沒法申請到足夠的內存)。
線程私有。
與虛擬機棧做用相似,爲虛擬機使用到的native方法服務。
StackOverflowError和OutOfMemoryError異常。
線程私有。
當前線程所執行的字節碼的行號指示器。若是線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;若是正在執行的是Native方法,這個計數器值則爲空(Undefined)。
1) 對象頭(Header)
Mark Word:用於存儲對象自身的運行時數據,如哈希碼(HashCode)、 GC分代年齡、 鎖狀態標誌、 線程持有的鎖、 偏向線程ID、 偏向時間戳等.
類型指針:即對象指向它的類元數據的指針,虛擬機經過這個指針來肯定這個對象是哪一個類的實例。若是對象是一個Java數組,那在對象頭中還必須有一塊用於記錄數組長度的數據。
2) 實例數據(Instance Data)
對象真正存儲的有效信息,也是在程序代碼中所定義的各類類型的字段內容。存儲順序會受到虛擬機分配策略(longs/doubles、 ints、 shorts/chars、bytes/booleans、 oops)參數和字段在Java源碼中定義順序的影響。
Java程序須要經過棧上的reference數據來操做堆上的具體對象。對象訪問方式有「使用句柄」和「直接指針」。
1) 使用句柄