Java虛擬機至關於一個抽象的計算機操做系統,其管理的內從區域大致上能夠分爲棧和堆,就像c或c++中對內存的分類同樣,但這樣的分類對於Java虛擬機來講太過粗淺,實際上Java虛擬機管理的內存區域分爲程序計數器、虛擬機棧、本地方法棧、堆和方法區,根據各區域是屬於線程私有仍是由線程共享,這些區域能夠分爲兩類,下面分別進行說明。c++
程序計數器是一塊較小的內存空間,它能夠看做是當前線程所執行的字節碼的行號指示器。每一個線程都有各自獨立的程序計數器,若是線程正在執行的是一個Java方法,那麼這個計數器記錄的是正在執行的虛擬機字節碼指令地址,若是正在執行的是Native方法,則程序計數器爲空(Undifined)。算法
** 此內存區域是惟一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError狀況的區域。 **性能
虛擬機棧也是線程私有的,它描述的是Java方法執行的內存模型:每一個方法在執行的同時都會建立一個棧幀(Stack Frame)用於存儲局部變量表、操做數棧、動態連接、方法出口等信息,每個方法從調用直至完成的過程,就對應着一個棧幀在虛擬機棧中入棧和出棧的過程。 虛擬機棧幀中,局部變量表是比較爲人所熟知的,也就是日常所說的「棧」,局部變量表所需的內存空間在編譯期間分配完成,當進入一個方法時,這個方法須要在棧幀中分配多大的局部變量空間是徹底肯定的,在方法運行期間不會改變局部變量表的大小。 虛擬機棧有兩種異常狀況:操作系統
本地方法棧與虛擬機棧類似,不過服務於本地方法,有些虛擬機將這兩個區域合二爲一。 本地方法棧中拋出異常的狀況與虛擬機棧相同。線程
一般來講,堆是Java虛擬機管理的內存中最大的一塊,被全部線程共享,在虛擬機啓動時建立,堆的做用就是存儲對象實例。 堆也是垃圾收集器所管理的主要區域,所以不少時候也被稱做「GC堆」。從內存回收的角度來看,因爲如今收集器基本都採用分代收集算法,所以堆還能夠被細分爲:新生代和老年代。再繼續細分能夠分爲:Eden空間、From Survivor空間、To Survivor空間等,從內存分配的角度來看,線程貢獻的堆中還能夠劃分出多個線程私有的分配緩衝區u(Thread Local Allocation Buffer,TLAB)。 堆能夠是物理上不連續的空間,只要邏輯上是連續的便可,-Xmx和-Xms參數能夠控制堆的最大和最小大小。 堆的空間大小不知足時將拋出OutOfMemoryError異常。code
用於存儲已被虛擬機加載的類信息、常量、靜態變量、JIT編譯後的代碼等數據。Java虛擬機規範將方法區描述爲堆的一個邏輯部分,可是它卻有一個別名叫作Non-Heap(非堆)。對象
方法區一樣會拋出OutOfMemoryError異常。遞歸
在方法區中有一部分區域用來存儲編譯期產生的各類字面量和符號引用,這部份內容將在類加載後進入方法區的運行時常量池中存放。 這裏須要說明一點,常量並非只能在編譯期產生,運行期間也會產生新的常量並被髮在常量池中,如String類的intern()方法。
本機直接內存並非Java虛擬機運行時數據區的一部分,但它能在一些場景中顯著提升性能,由於其避免了在Java堆和Native堆中來回複製數據。內存
直接內存一樣會拋出OutOfMemoryError異常。虛擬機