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

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


如上圖所示,首先java源代碼文件(.java後綴)會被java編譯器編譯爲字節碼文件(.class後綴)然後再讓類加載器加載各個類的字節碼文件,加載完畢後,交由JVM執行引擎執行。在整個執行過程中,JVM會用一段空間來存儲程序執行期間需要用到的數據和相關信息,這段控件一般稱之爲Runtime Data Area(運行時數據區),也就是我們常說的JVM內存。

Java虛擬機在執行java程序的過程中會把它所管理的內存劃分爲若干個不同的數據區域。這些區域都有各自的用途,以及創建和銷燬的時間,有的區域隨着虛擬機進程的啓動而存在,有些區域則會依賴用戶的線程的啓動和結束而建立和銷燬。


上述中方法區和堆是所有線程共享的數據區

上述的其他三個區是線程隔離數據區。

 

程序計數器:是一塊較小的內存空間,他可以是看作是當前線程所執行的字節碼的行數指示器。字節碼解釋器工作時就是通過改變這個計數器的值來選取下一個需要執行的字節碼指令。由於java虛擬機的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現,在任何一個確定的時刻,一個處理器都只會執行一條線程中的指令。因此爲了線程切換後能恢復到正確的執行位置,每個線程都需要一個獨立的程序計數器,各線程之間計數器互不影響,獨立存儲。

如果線程執行時一個java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令內存。執行的是native方法,這個計數器則爲空。次內存區域是唯一一個在java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。

 

虛擬機棧:java虛擬機棧也是線程私有的,他的生命週期和線程相同。虛擬機棧描述的是java方法執行的內存模型:每個方法在執行時都會創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每個方法從調用直到執行完畢,就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。

該區域規定了兩個異常情況:如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;如果虛擬機棧可以動態擴展,如果擴展是無法申請到足夠多的內存,就會拋出OutOfMemoryError異常。

 

本地方法棧:本地方法棧與虛擬機棧所發揮的作用非常類似,區別在於虛擬機棧爲虛擬機執行java方法服務,而本地方法棧則爲虛擬機使用到的native方法服務。

該區域規定了兩個異常情況:如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;如果虛擬機棧可以動態擴展,如果擴展是無法申請到足夠多的內存,就會拋出OutOfMemoryError異常。

 

Java堆:對於大多數應用來說,java堆是java虛擬機所管理的內存中最大的一塊。Java堆是被所有線程共享的一塊內存區域。所有的對象實例和數組都在堆上分配。堆是垃圾回收機制主要的區域,因此很多時候也被稱之爲GC堆,由於現在的垃圾回收機制所以java堆中還可以細分爲:新生代和老年代。

Java堆可以處於物理上不連續的內存空間中,只要邏輯上的連續即可。如果在堆中沒有內存完成實例分配,並且對也無法在擴展,將會拋出OutOfMemoryError異常。

 

方法區:方法區與java堆一樣,是各個線程所共享的內存區域,他是用來存儲已被虛擬機加載的類信息、常量、靜態變量等一些。

當方法區無法滿足內存分配要求的時候,將拋出OutOfMemoryError異常。

發佈了54 篇原創文章 · 獲贊 70 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章