JVM筆記二——內存結構(運行時數據區——親手翻譯的官方文檔)

JVM運行時數據區域(JDK1.8官方文檔)

定義:

       JVM運行時數據區域(Run-Time Data Areas),JVM定義了在程序執行期間使用的各種運行時數據區域。其中一些數據區域是在java虛擬機啓動時臨時創建,在Java虛擬機退出時銷燬。其他數據區域是單線程區域( Per-thread data areas),單線程區域是隨着線程創建、銷燬時創建銷燬的。

  1. 程序計數器(The PC Register)

程序計數器是處理器中的寄存器,用於指示計算機在其程序序列中的位置。它包含正在執行指令的當前位置,當每個指令被獲取,程序計數器的地址加一。在每個指令被獲取之後,程序計數器指向順序中的下一個指令。當計算機重啓,程序計數器置0。Java虛擬機可以支持多線程一次運行,在任何時候,每個java虛擬機線程都在執行單個方法的代碼,即該線程的當前方法。如果該方法不是本地方法,程序計數器就包含當前正在執行的java虛擬機指令的地址。如果當前線程正在執行的方法是本地的,程序計數器的值就是Undefined的。程序計數器的空間足夠大,可以保存在特定平臺的返回地址類型(returnAddress)或本地指針。

  1. Java虛擬機棧

每個java虛擬機線程都是一個私有的java虛擬機棧,與線程同時創建,同時銷燬。Java虛擬機棧類似於諸如傳統C語言的堆棧,他保存了局部變量和部分結果,並在方法的調用和返回中起作用。除了壓入和彈出棧幀外,Java虛擬機棧不會被直接操作棧幀,所以棧幀的分配可能是由堆完成的。(Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. 這段翻譯的不精確,有同學看得懂,麻煩指出來)Java虛擬機棧的內存是不連續的。

        在java虛擬機版本規範的第一版中,java虛擬機棧被稱作java棧。此規範允許java虛擬機棧具有固定大小或根據計算的需要動態擴展和收縮。如果每個Java虛擬機堆棧都具有固定大小,則可以在創建時獨立選擇每個java虛擬機堆棧的大小。

        Java虛擬機可以實現爲程序員或用戶提供對java虛擬機棧初始大小的控制,以及在動態擴展或收縮java虛擬機棧的情況下,控制最大值和最小值。

Java虛擬機棧有以下異常:

  1. 如果在一個線程請求所需要的內存大於java虛擬機棧的最大值,則會拋出StackOverflowError。
  2. 如果在動態擴展java虛擬機棧的過程中,可以使用的內存不足以支撐擴展,或者可使用的內存不足以爲新的線程創建java虛擬機棧,則java虛擬機棧會拋出OutOfMemoryError。

3、堆(HEAP)

Java虛擬機具有在所有線程之間共享的區域,堆。堆爲java虛擬機中所有的實例和數組分配內存。堆是在Java虛擬機啓動的時候創建的。對象的堆存儲由自動存儲管理系統(垃圾回收器)回收,對象永遠不會被顯示釋放。Java虛擬機假設沒有特定類型的自動存儲管理系統,可以根據實現者的系統要求選擇存儲管理技術。堆可以具有固定大小,也可以根據計算的需要進行擴展,並且如果不需要這麼大的內存,可以進行收縮。堆得內存是不連續的。Java虛擬機可以爲開發者或者用戶提供初始大小的控制,以及可以動態擴展或者收縮堆,控制最大值和最小值(maximum and minimum heap size)。

常見的堆異常:

如果計算所需要的堆內存超過自動存儲系統可用的堆內存,就會拋出OutOfMemoryError。

4、方法區(Method Area)

       方法區是所有線程共享的內存區域,是在java虛擬機啓動的時候創建的。方法區類似於傳統語言的編譯代碼的存儲區域,或類似於操作系統進程中的”文本段(text)”,它存儲了每個類的結構,例如運行時常量池,字段和方法數據,以及方法和構造函數的代碼,包括類和實例初始化中使用的特殊方法。

       雖然方法區在邏輯上是屬於堆的部分,但是垃圾收集器不會對它進行回收。本規範未規定方法區的位置,或用於管理管理編譯代碼的策略。方法區可以是固定大小的,也可以根據計算進行擴展,並且在不需要這麼大的時候,進行收縮該區域內存。方法區的內存同樣是非連續的。

常見的方法區異常:

如果計算所需要的方法區內存超過方法區可使用的內存,就會拋出OutOfMemoryError。

5、運行時常量池(Run-Time Constant Pool)

       運行時常量池是類文件中constant_pool表中類和運行時接口的表現形式,它包含幾種常量,從編譯時已知的數字到必須在運行時解析的方法和引用。運行時常量池提供類似於傳統編程語言的符號表的功能,而且它比傳統的符號表存儲的數據類型更豐富。每個運行時常量池都是從java虛擬機的方法區分配出來的。當Java虛擬機創建類和接口時,將構造類和接口的運行時常量池。

常見的運行時常量池異常:

創建或接口時,如果常量池的構造所需要的內存大於Java虛擬機方法區可使用的內存,就會拋出OutOfMemoryError。

6、本地方法棧(Native Method Stacks)

       Java虛擬機的實現可使用傳統的堆棧,俗稱爲“C堆棧”,用支持本地方法(用Java編程語言以外語言寫的方法)。一個不支持本地方法執行的JVM是不需要這個區域的。如果支持,則通常在創建線程時爲每個線程分配本地方法棧。

       此規範允許本機方法堆棧具有固定大小或根據計算的需要動態擴展和收縮。 如果本機方法堆棧具有固定大小,則可以在創建該堆棧時獨立地選擇每個本機方法堆棧的大小。

常見的關於本地方法棧的異常:

  1. 如果線程中的計算需要的堆棧內存比本地方法棧的內存更大是,則Java虛擬機會拋出StackOverflowError。
  2. 如果可以動態擴展本地方法堆棧並嘗試本機方法堆棧擴展但可用內存不足,或者如果可用內存不足以爲新線程創建初始本機方法堆棧,則Java虛擬機會拋出OutOfMemoryError。

 

官方文檔鏈接:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章