JVM基本概述

1、JVM體系結構預覽

注意:在運行時數據區中,亮色的表示一個進程的資源,存在垃圾回收。灰色的表示是每個線程私有的,另外內存佔的非常少,幾乎基本不存在垃圾回收機制。

2、類裝載器ClassLoader

注意:Class可以當成類的模版對象,相同的類在jvm中只有一個。sun.misc.Launcher 它是一個java虛擬機的入口應用。

1)雙親委派機制

當一個類收到了類加載請求,他首先不會嘗試自己去加載這個類,而是把這個請求委派給父類去完成,每一個層次類加載器都是如此,因此所有的加載請求都應該傳送到啓動類加載其中,只有當父類加載器反饋自己無法完成這個請求的時候(在它的加載路徑下沒有找到所需加載的Class),子類加載器纔會嘗試自己去加載。

採用雙親委派的一個好處是防止污染源代碼。

3、本地方法接口

本地接口的作用是融合不同的編程語言爲 Java 所用,它的初衷是融合 C/C++程序.於是就在內存中專門開闢了一塊區域處理標記爲native的代碼,它的具體做法是 Native Method Stack(上圖中的本地方法棧)中登記 native方法,在Execution Engine 執行時加載native libraies。

4、PC寄存器(程序計數器)

每個線程都有一個程序計數器,是線程私有的,就是一個指針,指向方法區中的方法字節碼(用來存儲指向下一條指令的地址,也即將要執行的指令代碼),由執行引擎讀取下一條指令,是一個非常小的內存空間,幾乎可以忽略不記。

字節碼解釋器通過改變這個計數器的值來選取下一條需要執行的字節碼指令。 如果執行的是一個Native方法,那這個計數器是空的。

用以完成分支、循環、跳轉、異常處理、線程恢復等基礎功能。不會發生內存溢出(OutOfMemory=OOM)錯誤。

5、方法區

供各線程共享的運行時內存區域。它存儲了每一個類的結構信息(Class),例如運行時常量池(Runtime Constant Pool)、字段和方法數據、構造函數和普通方法的字節碼內容。

注意:實例變量存在堆內存中,和方法區無關

6、Java 棧

棧管運行,堆管存儲。

棧也叫棧內存,主管Java程序的運行,是在線程創建時創建,它的生命期是跟隨線程的生命期,線程結束棧內存也就釋放,對於棧來說不存在垃圾回收問題,只要線程一結束該棧就Over,生命週期和線程一致,是線程私有的。8種基本類型的變量+對象的引用變量+實例方法都是在函數的棧內存中分配。

方法=棧幀

棧幀是一個內存區塊,是一個數據集,是一個有關方法(Method)和運行期數據的數據集,當一個方法A被調用時就產生了一個棧幀 F1,並被壓入到棧中,以此類推...(pc寄存器在此間使用)

遵循“先進後出”/“後進先出”原則。

每個方法執行的同時都會創建一個棧幀,用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息,每一個方法從調用直至執行完畢的過程,就對應着一個棧幀在虛擬機中入棧到出棧的過程。棧的大小和具體JVM的實現有關,通常在256K~756K之間,與等於1Mb左右。

7、堆

堆內存的大小是可以調節的,用來存儲類、方法、常變量,堆內存分爲三部分:

  物理上堆只包含新生區和養老區。永久區 (Java 8叫做元空間)。

1)新生區:新創建的對象實例首先會放在 新生代的Eden區(伊甸園)。

新生代的運行(MinorGC的過程(複製->清空->互換)):

新創建的對象會放在Eden區(伊甸園),當Eden空間滿了的時候會進行GC操作。稱之爲Minor GC

1:eden、SurvivorFrom 複製到 SurvivorTo,年齡+1

首先,當Eden區滿的時候會觸發第一次GC,把還活着的對象拷貝到SurvivorFrom區,當Eden區再次觸發GC的時候會掃描Eden區和From區域,對這兩個區域進行垃圾回收,經過這次回收後還存活的對象,則直接複製到To區域(如果有對象的年齡已經達到了老年的標準,則賦值到老年代區),同時把這些對象的年齡+1

2:清空 eden、SurvivorFrom

然後,清空Eden和SurvivorFrom中的對象,也即複製之後有交換,誰空誰是to

3:SurvivorTo和 SurvivorFrom 互換

最後,SurvivorTo和SurvivorFrom互換,原SurvivorTo成爲下一次GC時的SurvivorFrom區。部分對象會在From和To區域中複製來複制去,如此交換15次(由JVM參數MaxTenuringThreshold決定,這個參數默認是15),最終如果還是存活,就存入到老年代

注意:jvm給每個對象都分配了一個年齡,每一次移區年齡加一。

2)老年代

對象年齡大於15就會進入老年代,還有當Eden/Survivor空間不足內存分配擔保機制也會進入老年代,Old 老年代空間不足會引發 Full GC。

Full GC 是整堆進行清理,開銷比較大,響應時間較長。Minor GC 是對新生代空間進行清理。我們在JVM調優時要考慮 Full GC 執行的次數。

注意:實際而言,方法區(Method Area)和堆一樣,是各個線程共享的內存區域,它用於存儲虛擬機加載的:類信息+普通常量+靜態常量+編譯器編譯後的代碼等等,雖然JVM規範將方法區描述爲堆的一個邏輯部分,但它卻還有一個別名叫做Non-Heap(非堆),目的就是要和堆分開。

對於HotSpot虛擬機,很多開發者習慣將方法區稱之爲“永久代(Parmanent Gen)” ,但嚴格本質上說兩者不同,或者說使用永久代來實現方法區而已,永久代是方法區(相當於是一個接口interface)的一個實現。

 

 

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