區域簡介
JVM運行時區域有些隨着虛擬機進程的啓動而存在,有些依賴於用戶線程的啓動和結束而創建和銷燬,大體分爲如下幾類:方法區,虛擬機棧,本地方法棧,堆,程序計數器,概念圖以下(源於《深刻理解JAVA虛擬機-JVM高級特性》):函數

程序計數器
- 當前線程所執行的字節碼的行號指示器,是一塊各個線程私有的內存,每一個線程都有一個獨立的程序計數器;
- 若是線程執行的是一個JAVA方法,計數器記錄的是虛擬機字節碼指令的地址,若是執行的是一個Native方法,計數器值爲空(Undefined);
- 惟一一個在JVM規範中沒有規定任何OOM狀況的區域;
虛擬機棧
- 線程私有,每一個線程執行時會建立一個棧楨(Stack Frame),包括局部變量表、操做數棧、動態連接、方法出口等信息,一個方法的調用過程對應着一個棧楨在虛擬機棧中的入棧和出棧操做;
- 局部變量表:存放了編譯期可知的各類基本數據類型(byte、short、char、int、long、float、double、boolean),對象引用(reference),returnAddress類型(指向了一條字節碼指令的地址),64位的long和double佔用兩個Slot(局部變量空間),其餘佔用一個,局部變量表所需空間在編譯期就肯定;
- JVM規範中這個區域有兩種異常狀況,若是線程請求的棧深度大於虛擬機所容許的深度--拋出StackOverflowError,若是虛擬機棧可動態擴展但擴展時申請的內存沒法知足--拋出OutOfMerroyError;
本地方法棧
與虛擬機棧做用相似,區別在於本地方法棧用於執行Native方法,JVM規範並未對此區域的實現作強制規定,具體的虛擬機可自由實現,此區域也會拋出StackOverflowError和OutOfMerroyError;性能
堆
- 全部線程共享的區域,幾乎全部的對象實例都在這裏分配內存,之因此是幾乎,是由於JIT的優化技術已經使得部分對象實例沒必要在堆上分配;
- 從內存分配的角度看,堆中可能劃分出多個線程私有的分配緩衝區(Thread Local Allocation Buffer),目的是爲了更好回收內存或更快的分配內存;
- 邏輯上連續,物理上能夠不連續;
- 當堆中沒有足夠的內存完成對象實例的分配,且沒法再擴展,會拋出OOM;
方法區
- 線程共享區域,用於存儲已被虛擬機加載的類信息、常量、靜態變量、JIT產生的代碼等數據;
- HotSpot將永久代(Permanent Generation)做爲方法區的實現,但本質上與方法區並不等價;
- 不須要連續的內存,可擴展,能夠選擇不實現垃圾收集(GC只是hotspot在此區域實現的功能),當沒法知足內存分配需求時,會拋出OOM;
- 運行時常量池:Class文件中的常量池--用於存放編譯期生成的各類字面量和符號引用--將在類加載後進入方法區的運行時常量池,除此以外還會把翻譯出來的直接引用也存入,相對於Class文件常量池的特徵是動態性,運行期間也能夠將新的常量放入,如String.intern();
直接內存
此區域並不在JVM區域劃分範圍中,但這部分也可能會拋出OOM,NIO能夠經過Native函數庫直接分配堆外內存並經過DirectByteBuffer對象對這塊內存進行操做,由於避免了數據在Native堆和Java堆之間的複製從而提升性能;優化