Java內存區域與內存溢出異常

Java內存區域與內存溢出異常

Java虛擬機在執行Java程序的過程中會把它管理的內存分為不同的若干個數據區域。

具體的情況如下圖所示:

jvm
jvm

我們可以可到運行時數據區主要有以下幾個部分組成:

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

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

程序計數器(Program Count Register)

程序計數器是一塊比較小的內存區域,它的作用是:當前線程所助興的字節碼的符號顯示器。

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

這個區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。

Java虛擬機棧

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

這一部分描述的是Java方法執行的內存模型:

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

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

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

這個區域可能拋出兩種異常:

  1. 如果線程請求的棧深度大于虛擬機所允許的深度: 拋出StackOverflowError
  2. 如果虛擬機棧可以動態擴展,當擴展無法申請到足夠內存時,拋出OutOfMemoryError

本地方法棧

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

Java堆

我們嘗試總結Java堆的特性如下:

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

方法區

與Java堆一樣,方法區也是線程共享的內存區域。

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

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

運行時常量池(Runtime Constant Pool)

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

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容