聲明:本文參考周志明先生著作《深入理解Java虛擬機》而寫,更多詳細內容請參原著。
Java虛擬機在運行時將它所管理的內存劃分爲若干個不同的區域,根據《Java虛擬機規範(第二版)》規定,Java虛擬機所管理的內存將包含以下幾個運行時區域:
程序計數器
程序計數器是一塊較小的內存空間,它的作用可以看做當前線程所執行的字節碼的行號指示器。程序計數器是線程私有的,Java虛擬機支持多線程,爲了線程切換後能恢復到正確的執行位置,每個線程都需要有一個獨立的程序計數器,各個線程間的程序計數器互不影響。
Java虛擬機棧
Java虛擬機棧也是線程私有的,虛擬機棧描述的是Java方法執行的內存模型:每個方法被執行的時候都會同時創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。
在Java虛擬機規範中,對這個區域規定了兩種異常情況:如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常;如果虛擬機棧可以動態擴展,當擴展時無法申請到足夠的內存時會拋出OutOfMemoryError異常。
本地方法棧
本地方法棧與虛擬機棧發揮的作用非常相似,其區別是虛擬機棧爲Java方法服務,本地方法棧爲Native方法服務。
Java堆
Java堆不是線程私有的,是被所有線程共享的一塊內存區域,在虛擬機啓動時創建,幾乎所有對象實例以及數組都要在堆上分配。Java堆是垃圾回收器管理的主要區域,可以分爲新生代和老年代等。這個區域不一定是物理上連續的空間,只要在邏輯上連續即可。
Java虛擬機規範中規定:如果在堆中沒有足夠的內存來分配實例,並且堆也無法再擴展時,將會拋出OutOfMemoryError異常。
方法區
方法區也是各個線程共享的區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。這個區域和堆一樣,也不一定是物理上連續的空間,只要在邏輯上連續即可。
Java虛擬機規範規定:當方法去無法滿足內存分配需求時,將拋出OutOfMemoryError異常。
運行時常量池
運行時常量池是方法區的一部分,用於存放Class文件中的常量池信息。運行時常量池相對於Class文件常量池的一個重要特徵是具備動態性,並非Class文件常量池的內容才能進入運行時常量池,運行期間也可能將新的常量放入池中。
運行時常量池是方法區的一部分,自然受到方法區的內存限制,當常量池無法申請到內存時拋出OutOfMemoryError異常。