我們常常做的是將Java內(nèi)存區(qū)域簡單的劃分為兩種: 一種叫做棧內(nèi)存,一種叫做堆內(nèi)存。
棧內(nèi)存
棧內(nèi)存又分兩種,一種是虛擬機(jī)棧,一種是本地方法棧。
本地方法棧是去調(diào)用native方法服務(wù),和java關(guān)系不算太大。
虛擬機(jī)棧就牛逼了,它里面存了局部變量表,操作棧,動態(tài)鏈接,方法出口等信息。
局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型,對象引用和一條字節(jié)碼指令的地址。
其中64位長度的long和double類型的數(shù)據(jù)會占用2個局部變量空間,其余的基本類型占1個。
當(dāng)進(jìn)入一個方法時,這個方法需要分配多大的局部變量空間是完全確定的,在運行期間不會改變變量表的大小。
在java虛擬機(jī)規(guī)范中,這個區(qū)域會有兩種異常情況產(chǎn)生,如果線程請求的棧深度大于虛擬機(jī)所允許的深度,將會拋出StackOverflowError異常。如果沒有處理好遞歸調(diào)用的出口條件,很容易就會報這樣的錯。
如果虛擬機(jī)棧動態(tài)擴(kuò)展的時候無法申請最夠的內(nèi)存,就會拋出OutOfMemoryError異常。
堆內(nèi)存
Java的堆是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊。
堆的唯一目的就是存放對象實例。所有的對象實例都會在這里分配內(nèi)存。
堆產(chǎn)生了一個對象之后,還能夠在棧里面定義一個變量指向堆的的首地址。
如果這個對象沒有被引用,那么不一會就會被java當(dāng)作垃圾回收,因此Java堆是垃圾收集的管理主要區(qū)域。
如果在堆中沒有內(nèi)存完成實例分配,并且堆也無法再擴(kuò)展時,將會拋出OutOfMemoryError異常。
參考資料
深入理解java虛擬機(jī)