Java內(nèi)存區(qū)域與內(nèi)存溢出異常

Java內(nèi)存區(qū)域與內(nèi)存溢出異常

Java虛擬機(jī)在執(zhí)行Java程序的過程中會把它管理的內(nèi)存分為不同的若干個數(shù)據(jù)區(qū)域。

具體的情況如下圖所示:

jvm
jvm

我們可以可到運行時數(shù)據(jù)區(qū)主要有以下幾個部分組成:

  1. 程序計數(shù)器(Program Counter Register)
  2. Java虛擬機(jī)棧(VM Stack)
  3. 本地方法棧(Native Method Stack)
  4. Java堆(Heap)
  5. 方法區(qū)

我們一個個看分析一下這些部分的功能和特點。

程序計數(shù)器(Program Count Register)

程序計數(shù)器是一塊比較小的內(nèi)存區(qū)域,它的作用是:當(dāng)前線程所助興的字節(jié)碼的符號顯示器。

這里有一個需要注意的地方,即【當(dāng)前線程】,也就是說程序計數(shù)器是每個線程獨享的,它用于在線程切換后能恢復(fù)到上一次的正確執(zhí)行位置。

這個區(qū)域是唯一一個在Java虛擬機(jī)規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。

Java虛擬機(jī)棧

Java虛擬機(jī)棧也是線程私有的,它的生命周期與線程相同。

這一部分描述的是Java方法執(zhí)行的內(nèi)存模型:

每個方法被執(zhí)行的時候都會創(chuàng)建一個棧幀(Stack Frame),用于存儲局部變量表等信息。每一個方法被調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀從入棧到出棧的過程。

在虛擬機(jī)棧中最重要的部分是局部變量表, 存放了編譯期可知的基本數(shù)據(jù)類型,對象引用等等。

局部變量表所需的內(nèi)存空間在編譯期完成分配。

這個區(qū)域可能拋出兩種異常:

  1. 如果線程請求的棧深度大于虛擬機(jī)所允許的深度: 拋出StackOverflowError
  2. 如果虛擬機(jī)??梢詣討B(tài)擴(kuò)展,當(dāng)擴(kuò)展無法申請到足夠內(nèi)存時,拋出OutOfMemoryError

本地方法棧

本地方法棧與虛擬機(jī)棧基本一致,不同的是本地方法棧是位虛擬機(jī)使用到的Native方法服務(wù)的。在有些虛擬機(jī)中(Sun HotSpot),直接把本地方法棧和虛擬機(jī)棧合二為一了。

Java堆

我們嘗試總結(jié)Java堆的特性如下:

  • Java堆是被所有線程共享的一塊內(nèi)存區(qū)域
  • 在虛擬機(jī)啟動時創(chuàng)建
  • 這一區(qū)域的目的是:存放對象實例
  • Java堆是垃圾收集器管理的主要區(qū)域,因此很多時候也被稱為“GC堆”
  • Java堆可以處于物理上不連續(xù)的內(nèi)存空間,只要在邏輯上連續(xù)就行了

方法區(qū)

與Java堆一樣,方法區(qū)也是線程共享的內(nèi)存區(qū)域。

它用于存儲已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等等。

垃圾收集行為在這個區(qū)域比較少見,回收目標(biāo)主要是常量池的回收和對類型的卸載。

運行時常量池(Runtime Constant Pool)

運行時常量池是方法區(qū)的一部分,用于存放編譯器生成的各種字面量和符號引用。

運行時常量池具備動態(tài)性,運行期間也可以將新的常量放入池中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容