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