方法區 Method Area
方法區是各個線程共享的內存區域,在虛擬機啓動時創建。
用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。
雖然Java虛擬機規範把方法區描述爲堆的一個邏輯部分,但是它卻又一個別名叫做Non-Heap(非堆),目的是與Java堆區分開來。
當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError異常。
注意:
- 方法區在JDK 8中是叫 Meta space ,而在JDK6、7中叫 perm space
- 運行時常量池 run time constant pool
Class文件中除了有類的版本、字段、方法、接口等描述 信息外,還有一項信息就是常量池,用於存放編譯時期生
成的各種字面量和符號引用,這部分內容將在類加載後進 入方法區的運行時常量池中存放。
堆 heap
Java堆是Java虛擬機所管理內存中最大的一塊,在虛擬機啓動時創建,被所有線程共享。
Java對象實例以及數組都在堆上分配。
虛擬機棧
虛擬機棧是一個線程執行的區域,保存着一個線程中方法的調用狀態。換句話說,一個Java線程的運行狀態,由一
個虛擬機棧來保存,所以虛擬機棧肯定是線程私有的,獨有的,隨着線程的創建而創建。
每一個被線程執行的方法,爲該棧中的棧幀,即每個方法對應一個棧幀。
調用一個方法,就會向棧中壓入一個棧幀;一個方法調用完成,就會把該棧幀從棧中彈出。
棧楨:每個棧幀對應一個被調用的方法,可以理解爲一個方法的運行空間。
每個棧幀中包括局部變量表(Local Variables)、操作數棧(Operand Stack)、指向運行時常量池的引用(A reference to the run-time constant pool)、方法返回地址(Return Address)和附加信息。
局部變量表(Local Variables)
方法中定義的局部變量以及方法的參數存放在這張表中
局部變量表中的變量不可直接使用,如需要使用的話,必須通過相關指令將其加載至操作數棧中作爲操作數使用。
操作數棧(Operand Stack)
以壓棧和出棧的方式存儲操作數的
動態鏈接
每個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用,持有這個引用是爲了支持方法調用過程中的 動態連接(Dynamic Linking)。
方法返回地址
當一個方法開始執行後,只有兩種方式可以退出,一種是遇到方法返回的字節碼指令;一種是遇見異常, 並且這個異常沒有在方法體內得到處理。
程序計數器 The pc Register
我們都知道一個JVM進程中有多個線程在執行,而線程中的內容是否能夠擁有執行權,是根據CPU調度來
的。
假如線程A正在執行到某個地方,突然失去了CPU的執行權,切換到線程B了,然後當線程A再獲得CPU執行
權的時候,怎麼能繼續執行呢?這就是需要在線程中維護一個變量,記錄線程執行到的位置。
程序計數器佔用的內存空間很小,由於Java虛擬機的多線程是通過線程輪流切換,並分配處理器執行時間的方式來
實現的,在任意時刻,一個處理器只會執行一條線程中的指令。因此,爲了線程切換後能夠恢復到正確的執行位
置,每條線程需要有一個獨立的程序計數器(線程私有)。
如果線程正在執行Java方法,則計數器記錄的是正在執行的虛擬機字節碼指令的地址;
如果正在執行的是Native方法,則這個計數器爲空。
本地方法棧 Native Method Stacks
如果當前線程執行的方法是Native類型的,這些方法就會在本地方法棧中執行。