Java和C++之間有一堵由內存管理和垃圾收集技術所圍成的「高牆」,牆外的人想進去,牆內的人卻想出來。 ------摘自《深刻理解Java虛擬機》程序員
做爲一個Java程序員,由於虛擬機的好處,在開發過程當中通常不用關心內存分配和垃圾回收方面的內容,這就讓我在跟C++的朋友聊天或溝通的時候,總以爲本身是個假的程序員,雖然咱們不用本身動手去作這兩件事情,但仍是頗有必要去了解一下這方面的原理,這樣萬一真碰到內存溢出的問題,就不至於一籌莫展了。下面是經過看書總結的一些內容。數組
1、Java內存區域劃分數據結構
Java虛擬機在執行Java程序的過程當中,會把它所管理的內存區域劃分紅不一樣的數據區域,沒有數據區域都有各自的功能、建立和銷燬時間,有些隨着虛擬機的啓動而產生,有些隨着用戶線程的建立和結束而產生和銷燬,根據《Java虛擬機規範》的規定,Java虛擬機所管理的內存將會包含下面幾個部分:spa
從上圖可知,Java虛擬機內存主要由線程共享的堆內存、方法區和線程私有的虛擬機棧、本地方法棧和程序計數器五個運行時數據區。線程
2、各運行時數據區的功能介紹對象
一、程序計數器內存
1)程序計數器是當前線程所執行的字節碼的行號指示器,存放下一個要執行的字節碼位置;開發
2)此內存區域是惟一一個在Java虛擬機規範中沒有任何OutOfMemoryError異常的區域;編譯器
3)線程私有虛擬機
二、Java虛擬機棧
1)Java虛擬機棧是方法執行的內存模型,通俗點說就是執行方法是進行內存管理的區域。
方法執行時,會建立一個棧幀,用於存儲方法中的局部變量、操做數、動態連接和方法出口等信息,方法的調用執行過程就是一個棧幀在虛擬機棧中進行入棧出棧的過程;
2)線程私有,隨着線程的開始而建立,線程的結束而銷燬;
3)一般所說的Java棧內存就是指Java虛擬機棧中的局部變量表,它存放了編譯期可知的基本類型(boolean、byte、char、short、int、long、float、dounle)、對象引用和returnAddress類型。局部變量的大小在程序編譯期就已經完成,並且在方法執行期間不會被改變;
4)此區域可能發生的異常有:
StackOverflowError:當線程請求的棧深度超過Java虛擬機所容許的棧深度時,會發生棧溢出異常;
OutOFMemoryError:當虛擬機棧在動態擴展過程當中沒有申請到足夠的內存時,會發生內存溢出異常;
三、本地方法棧
1)同虛擬機棧,本地方法棧也是Java方法執行的內存模型,區別在於虛擬機棧是爲Java程序在虛擬機中執行服務的,而本地方法棧是爲本地方法在Java虛擬機中執行服務的。在虛擬機規範中,對本地方法棧中的方法所使用的語言、使用方法和數據結構都沒有強制規定;
2)線程私有
3)可拋出兩種異常:
StackOverflowError:當線程請求的棧深度超過Java虛擬機所容許的棧深度時,會發生棧溢出異常;
OutOFMemoryError:當虛擬機棧在動態擴展過程當中沒有申請到足夠的內存時,會發生內存溢出異常;
四、Java堆
1)堆內存是Java虛擬機所管理的內存中最大的一塊;
2)線程共享,在虛擬機啓動時建立;
3)用來存放對象實例和數組;
4)堆是垃圾收集器管理的主要區域,所以也稱GC堆;
5)堆內存可擴展,可經過參數--Xmx和--Xms來設置最大堆內存和最小堆內存來控制;
6)若是堆中沒有足夠的內存來分配實例,且堆沒法擴展時就會拋出OutOfMemoryError異常
五、方法區
1)同堆內存同樣,方法區也是線程共享的內存區域;
2)用來存儲已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據;
3)根據Java虛擬機規範,當方法區沒法知足內存分配需求時就會拋出OutOfMemoryError異常
六、直接內存
這部份內存既不是Java虛擬機運行時數據區,也不是Java虛擬機規範中定義的內存區域,可是這部份內存也會被頻繁使用,並且還有可能引發OutOfMemoryError異常。本機內存的分配不會受到Java虛擬機內存分配的影響,可是當虛擬機中各區域的內存之和大於本機內存的話,就會致使動態擴展時出現OutOfMemoryError異常
以上就是Java虛擬機中的內存模型及各內存在程序運行過程當中所扮演的角色或所起的做用。下節將會總結各個內存區域出現內存溢出異常的緣由和解決方法。
備註:以上內容來源於《深刻理解Java虛擬機》,根據本身的理解來總結,有些內容和書本內容相同是由於只有這麼描述才比較好懂,畢竟大神仍是大神,是顏色不同的煙火!!