1. 程式人生 > 其它 >JVM之基本結構

JVM之基本結構

JVM之基本結構

 

 

 

 

JVM之記憶體空間:方法區、java堆、java棧、本地方法棧

JVM記憶體空間包含:方法區、java堆、java棧、本地方法棧。

 

方法區

簡單的說:

-----方法區是各個執行緒共享的區域,存放類資訊、常量、靜態變數。

 

細得說:

----- 靜態變數+常量+類資訊+執行時常量池存在方法區中,例項變數存在堆記憶體中。

java堆(Heap 堆)

java堆也是執行緒共享的區域,

我們的類的例項就放在這個區域,可以想象你的一個系統會產生很多例項,因此java堆的空間也是最大的。如果java堆空間不足了,程式會丟擲OutOfMemoryError異常。

 

也就是(Heap 堆)

 

往細得走(有興趣的可以看看):

堆這塊區域是JVM中最大的,應用的物件和資料都是存在這個區域,這塊區域也是執行緒共享的,也是 gc 主要的回收區,一個 JVM 例項只存在一個堆類存,堆記憶體的大小是可以調節的。

又分為三個部分:

 

 

 

① 新生區

新生區是類的誕生、成長、消亡的區域,一個類在這裡產生,應用,最後被垃圾回收器收集,結束生命。新生區又分為兩部分:伊甸區(Eden space)和倖存者區(Survivor pace),所有的類都是在伊甸區被new出來的。倖存區有兩個:0區(Survivor 0 space)和1區(Survivor 1 space)。當伊甸園的空間用完時,程式又需要建立物件,JVM的垃圾回收器將對伊甸園進行垃圾回收(Minor GC),將伊甸園中的剩餘物件移動到倖存0區。若倖存0區也滿了,再對該區進行垃圾回收,然後移動到1區。那如果1去也滿了呢?再移動到養老區。若養老區也滿了,那麼這個時候將產生Major GC(FullGCC),進行養老區的記憶體清理。若養老區執行Full GC 之後發現依然無法進行物件的儲存,就會產生OOM異常“OutOfMemoryError”。

 

重點:

如果出現java.lang.OutOfMemoryError: Java heap space異常,說明Java虛擬機器的堆記憶體不夠。原因有二:

 

Java虛擬機器的堆記憶體設定不夠,可以通過引數-Xms、-Xmx來調整。

程式碼中建立了大量大物件,並且長時間不能被垃圾收集器收集(存在被引用)。

② 養老區

養老區用於儲存從新生區篩選出來的 JAVA 物件,一般池物件都在這個區域活躍。

 

③ 永久區

永久儲存區是一個常駐記憶體區域,用於存放JDK自身所攜帶的 Class,Interface 的元資料,也就是說它儲存的是執行環境必須的類資訊,被裝載進此區域的資料是不會被垃圾回收器回收掉的,關閉 JVM 才會釋放此區域所佔用的記憶體。

 

重點:

如果出現java.lang.OutOfMemoryError: PermGen space,說明是Java虛擬機器對永久代Perm記憶體設定不夠。原因有二:

 

程式啟動需要載入大量的第三方jar包。例如:在一個Tomcat下部署了太多的應用。

大量動態反射生成的類不斷被載入,最終導致Perm區被佔滿。

java棧(Stack 棧)

java棧

是每個執行緒私有的區域,它的生命週期與執行緒相同,一個執行緒對應一個java棧,每執行一個方法就會往棧中壓入一個元素,這個元素叫“棧幀”,而棧幀中包括了方法中的區域性變數、用於存放中間狀態值的操作棧。

 

如果java棧空間不足了,程式會丟擲StackOverflowError異常,想一想什麼情況下會容易產生這個錯誤,對,遞迴,遞迴如果深度很深,就會執行大量的方法,方法越多java棧的佔用空間越大。

 

堆記憶體與棧記憶體需要說明:

 

基礎資料型別直接在棧空間分配,方法的形式引數,直接在棧空間分配,當方法呼叫完成後從棧空間回收。引用資料型別,需要用new來建立,既在棧空間分配一個地址空間,又在堆空間分配物件的類變數 。方法的引用引數,在棧空間分配一個地址空間,並指向堆空間的物件區,當方法呼叫完成後從棧空間回收。區域性變數new出來時,在棧空間和堆空間中分配空間,當局部變數生命週期結束後,棧空間立刻被回收,堆空間區域等待GC回收。方法呼叫時傳入的literal引數,先在棧空間分配,在方法呼叫完成後從棧空間收回。字串常量、static在DATA區域分配,this在堆空間分配。陣列既在棧空間分配陣列名稱,又在堆空間分配陣列實際的大小。

本地方法棧

 就是Java虛擬機器在呼叫本地方法時,需要給本地方法提供的一塊空間什麼又是本地方法呢? 就是那些 不是由Java程式碼編寫的方法 科普,因為Java程式碼有限制,有些情況下不能和作業系統底層進行互動,所以就需要由C 或 C++ 編寫的本地方法來與作業系統打交道 所以本地方法執行時候所使用的就是本地方法棧。

舉例

這樣的本地方法其實是很多的,但有些同學說我沒見過這些本地方法啊?或者說什麼樣的才是稱為本地方法呢? 帶大家看下

object 是所有Java的父類,可以看到object的clone() 克隆方法就是做一個物件的克隆 可以看到修飾符是native可以看到native修飾的方法是沒有方法實現的,他都是由底層C或者C++ 進行實現的 然後Java程式碼間接的呼叫 native 方法, 通過本地native方法的介面,間接的去呼叫底層實現