JVM結構及GC機制

GC主要用於管理 JVM 的 堆區,所以先介紹一下 JVM的內存分配
安卓啓動優化


JVM主要包括:程序計數器,Java虛擬機棧區,本地方法棧,堆區,方法區
在Java中,對象實例都是在堆上創建。
方法區(靜態成員區):1 類(class) 2 靜態變量(static變量) 3 靜態方法 4 常量 5 成員方法,都存儲在方法區
堆和方法區都是線程共享的。

在這裏插入圖片描述


1 程序計數器( Program Counter Register)

程序計數器是一塊小的內存空間,它是當前線程執行字節碼行號指示器字節碼解釋工作器就是通過改變這個計數器的值,來選取下一條需要執行的指令。它是線程私有的內存,也是唯一 一個 沒有 OOM異常的區域。

2 Java虛擬機棧區( Java Virtual Machine Stacks)

是通常所說的棧區,它描述的是Java方法執行的內存模型,每個方法被執行的時候,都創建一個幀棧(Stack Frame),用於存儲局部變量表,操作數棧,動態鏈接,方法出口等。每個方法被調用完成,相當於一個幀棧在虛擬機棧中,從入棧到出棧的過程。此區域是線程私有內存,可能拋出兩種異常:

線程請求的棧深度,大於虛擬機允許的深度,,拋出 StackOveflowError異常
虛擬機在擴展棧時,無法申請到足夠的內存空間,拋出OOM(OutOfMemoryError)異常

這裏把異常分爲兩種情況,看似更加嚴謹,但卻存在一些互相重疊的地方:當棧空間無法繼續分配時,到底是內存太小,還是已使用的棧空間太大,其本質上只是對同一件事情的兩種描述 — 詳見 JVM書53頁

3 本地方法棧( Native Method Stacks)

本地方法棧與虛擬機棧發揮的作用非常相似,區別就是虛擬機棧爲 虛擬機執行Java方法,本地方法棧是爲 虛擬機使用到的 Native方法 服務

4 堆區( Heap)

所有對象實例和數組都在堆區上分配,堆區是GC主要管理的區域。堆區還可以細分爲新生代,老年代,新生代還分爲一個Eden區和兩個Survivor區。此塊內存爲所有線程共享區域。當堆中沒有足夠內存完成實例分配時,會拋出OOM異常。
根據對象的使用頻率,不斷的從新生代往老年代轉移,頻率越高,轉移機率越大,頻率不高,會在 Eden中就被回收。
新生代 Eden區和兩個 Survivor區的比例大概是 8:1:1
在這裏插入圖片描述

在這裏插入圖片描述
5 方法區( Method Area)

方法區與堆區一樣,是各個線程共享的區域,用於存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯後的代碼等數據。
GC在這個區域很少出現,這個區域內存回收的目標主要是對常量池的回收和類型的卸載,回收的內存比較少,所以也有稱這個區域爲永久代(Permanent Generation)的。當方法區無法滿足內存分配時,拋出OOM異常。
雖然 Java虛擬機規範把方法區描述爲堆的一個邏輯部分,但是它卻有一個別名叫做 Non-Heap(非堆),目的應該是與 Java堆 區分開來

6 運行時常量池(Runtime Constant Pool)

運行時常量池是方法區的一部分,用於存放編譯期生成的各種字面量符號引用

運行時數據區,即我們說的內存
在這裏插入圖片描述

黃色代表線程共享,藍色代表非線程共享
在這裏插入圖片描述
在這裏插入圖片描述

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