JVM 內存模型分析(通俗易懂)

 JVM(Java 虛擬機)主要包括五塊區域,分別是程序計數器、虛擬機棧、本地方法棧、堆、方法區。在 JVM 當中堆和方法區各有一個,一條線程有一個棧和一個程序計數器。五塊區域中當中變化最頻繁是棧,最先有數據的是方法區,垃圾回收器主要針對的是堆。

  1. 程序計數器(PC 寄存器)

        由於在 JVM 中多線程是通過線程輪流切換來換取 CPU 執行時間的,在任何一個確定的時刻,一個 CPU 只會執行一條線程的指令。因此,爲了線程切換後能恢復到正確的執行位置,每條線程都需要一個獨立的程序計數器。

        程序計數器佔用內存空間非常小,是線程私有的,每個線程運行的時候都會有一個獨立的計數器,是 Java 虛擬機規範中唯一一個沒有規定任何 OutOfMemoryError 情況的區域。如果程序執行的時候線程執行的是一個 Java 方法,計數器是有值的,其記錄的是程序正在執行的字節碼指令的地址;如果執行的是 Natvie 方法,計數器的值則爲空(Undefined)。

  1. 虛擬機棧

         Java 虛擬機棧是線程私有的,生命週期和線程一致,存儲的是一個個棧幀,每個棧幀對應着一個被調用的方法。方法調用的時候,該方法所需的內存空間在棧內存中分配,稱爲壓棧。方法執行結束之後,該方法所屬的內存空間釋放,稱爲彈棧(棧內存遵循先進後出,後進先出的原則)。虛擬機棧中主要存儲的是局部變量、引用、操作數棧、動態鏈接、方法的出口等信息。

Java 虛擬機規範中,對這個區域規定了兩個異常情況:

  1. 本地方法棧

        本地方法棧與 Java 虛擬機棧的的作用和原理非常相似,其區別只不過是虛擬機棧爲虛擬機執行 Java 方法(也就是字節碼)服務,而本地方法棧則是爲虛擬機使用到的 Native 方法服務。

本地方法棧區域也會拋出 StackOverflowError 和 OutOfMemoryError 異常。

        對於大多數應用來說,這塊區域是 JVM 所管理的內存中最大的一塊。堆是被所有線程共享的一塊區域,在虛擬機創建時啓動。堆當中主要存儲的是對象實例和數組,在程序執行過程中使用 new 運算符創建的 Java 對象,存儲在堆內存當中。對象內部有實例變量,所以實例變量存儲在堆內存當中。是垃圾回收機制主要管理的區域。

Java 虛擬機規範中,對這個區域規定了一個異常情況:

  1. 方法區

        方法區與堆一樣是各個線程共享的區域,主要存儲了類信息(類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯後的代碼片段(在類被加載的時候代碼片段會載入)等。

        在 Class 文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。

        在方法區中有一個非常重要的部分就是運行時常量池,它是每一個類或接口的常量池的運行時表示形式,在類和接口被加載到 JVM 後,對應的運行時常量池就被創建出來。當然並非 Class 文件常量池中的內容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,比如 String 的 intern 方法。內存有限,無法申請時拋出 OutOfMemoryError 異常。

  1. 垃圾回收器【自動垃圾回收機制、GC 機制】什麼時候會考慮將某個 Java 對象的內存回收呢?

         沒有更多的引用指向它的時候。

         這個對象無法被訪問,因爲訪問對象只能通過引用的方式訪問。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/mTMYBl5RW7P_GqECV11Yvw