jvm的內存結構
jvm的內存結構如圖所示

1.程序計數器
- 程序計數器是一塊較小的內存空間,它可以看做是當前線程執行的字節碼寫的行號指示器。他是線程私有的,按照我的理解就是,它相當於馬路上的路標,當程序執行的時候,他會獲取相應的指令,讓代碼運行下去,程序計數器是java虛擬機中唯一沒有 OutOfMemoryError情況的區域
2.Java虛擬機棧
- Java虛擬機棧和程序計數器一樣是線程私有的,他的生命周期和線程相同,當運行每個方法的時候都會創建一個棧幀,這里面存儲局部變量表,操作數棧,動態鏈接,方法出口等信息。
- 局部變量表就是儲存的基本數據類型(\boolean,byte,char,short,int,float,long,double),對象引用等等,long和double會占用2個局部變量的空間,其余的數據類型都只占用1個,方法運行期間局部變量表的大小固定
- Java 虛擬機棧規定了兩種異常,線程請求棧的深度大於當前虛擬機所允許的深度,會拋出StackOverflowError異常(比如遞歸的時候)還有就是當虛擬機棧擴展時無法申請到足夠的內存會有OutOfMemoryError異常。
3.本地方法棧
- 本地方法棧和Java虛擬機棧所發揮的作用非常相似,他們之間的區別就是Java虛擬機棧執行的Java方法,本地方法棧執行的是native方法,本地方法棧和Java虛擬機棧一樣都會有StackOverflowError和OutOfMemoryError異常
4.Java堆
- Java堆是虛擬機內存中最大的一塊,他是線程共享的,唯一的作用就是存放對象的實例,幾乎所有的對象實例都在堆里面分配內存,
- Java 堆是垃圾收集器管理的主要區域,
- Java 堆可以細分為:新生代和老年代,再詳細就分為:Eden(伊甸園)空間,From Survivor和To Survivor(幸存者)空間等,這樣分配主要目的是為了更好地回收內存
- Java堆可以處於物理上不連續的空間,只要邏輯上連續即可,Java堆可以通過-Xmx和-Xms來控制大小當堆沒有內存完成實例分配的時候,會拋出OutOfMemoryError異常
5.方法區
- 方法區(永久代)也是線程共享的內存區域,他用於儲存一杯虛擬機加載的類的信息,常量,靜態變量,即時編譯器編譯后的代碼等數據。
- 方法區的大小可以通過-XX:MaxPermSize設置上限,當無法滿足內存分配需求時會拋出OutOfMemoryError異常
- 方法區不需要連續的內存,可以選擇固定大小,可擴展,還能選擇不實現垃圾收集
6.運行時常量池
- 運行時常量池是方法區的一部分,它用於存儲編譯器生成的字面量(常量和未翻譯的引用
)和符號引用(一組符號來描述所引用的目標)也會有OutOfMemoryError異常
7.直接內存
- 直接內存(Direct Memory)並不是虛擬機運行時數據區的一部分,也不是Java虛擬機規范中定義的內存區域。但是這部分內存也被頻繁地使用,而且會導致OutOfMemoryError異常。
- 在NIO中,它可以使用Native函數庫直接分配堆外內存,然后通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊內存的引用進行操作。這樣做顯著提高了性能,避免在Java堆和Native堆中來回復制數據。
- 雖然這部分空間不會受到Java堆大小的限制,但是,因為是內存空間,所以會受到本機總內存大小以及處理器尋址空間的限制。
- 所以在配置虛擬機參數時,不能忽略直接內存,避免使各個內存區域總和大於物理內存限制。不然會導致動態擴展時出現OutOfMemoryError異常。