jvm在執行的過程當中會把它所管理的內存劃分爲若干個不一樣的數據區域,這些數據區域中,有些依賴着用戶線程的啓動和結束而創建和銷燬,有些則隨着jvm進程的啓動而建立java
jvm的運行數據區域能夠分爲兩種:線程私有和線程共享數組
線程私有: 每一個線程的私有數據,包括: 程序計數器、java虛擬機棧、本地方法棧jvm
線程共享: 全部線程共享的部分,包括: Java 堆、方法區、常量池spa
jvm內存區域劃圖示線程
程序計數器是較小的內存空間,它能夠看作是當前線程所執行的字節碼的行號指示器,用來執行選取小一條須要執行的字節碼指令,屬於線程私有的內存cdn
若是執行的是一個java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令地址,若是執行的是Native方法,這個計數器值爲空對象
虛擬機棧,也是線程私有的,它的生命週期與線程相同,每一個方法在執行時都建立一個棧幀,每一個方法從調用到執行完成,對應着一個棧幀的入棧到出棧blog
虛擬機棧描述的是java方法執行的動態內存模型生命週期
棧幀存儲的數據包括: 局部變量表,操做數棧,動態連接,方法出口等信息進程
在虛擬機棧中,規定了兩種異常:
線程私有,與虛擬機棧提供的功能相似,只不過執行的是本地方法,也就是用Native修飾的方法
堆是被線程共享的一塊內存區域,隨着jvm的啓動而建立,用來存放對象實例和數組
這塊區域也是GC進行垃圾回收的主要區域,當申請不到空間時會拋出 OutOfMemoryError異常
堆能夠細分爲新生代和老年代,新生代用來存放存活時間較短的對象,老年代用來存放存活時間較長的對象,新生代還能夠細分爲一個Eden區和兩個Survivor;
方法區也是被線程共享的一塊內存區域,用來存虛擬機中加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等數據
方法區是jvm的規範,而接下來要說的永久代和元空間正式jvm規範的一種實現
永久代(Permanent Space)
在jdk1.7時,方法區被叫作永久代(Permanent Space),因爲方法區主要存儲類的相關信息,因此對於動態生成類的狀況比較容易出現永久代的內存溢出,當永久代出現內存溢出,會拋出java.lang.OutOfMemoryError: PermGen space異常
元空間(MetaSpace)
在jdk1.8中移除了永久代,使用元空間代替,jdk1.7中,存儲在永久代的部分數據就已經轉移到了堆內存或者是直接內存。但永久代仍存在於jdk1.7中,並沒徹底移除,譬如符號引用(Symbols)轉移到了直接內存;字面量(interned strings),類的靜態變量(class statics)轉移到了堆內存
元空間的本質和永久代相似,都是對JVM規範中方法區的實現。不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存。所以,默認狀況下,元空間的大小僅受本地內存限制,但能夠經過如下參數來指定元空間的大小:
參考:深刻理解java虛擬機第二版