1. 程式人生 > >目錄 1.1. JVM記憶體模型總體架構圖 1 1.2. JAVA堆 2 1.3. 方法區 元空間(Metaspace) 2 1.4. 虛擬機器棧 3 1.5. 本地方法區 4 2. 垃圾回收演算法 4 2

目錄 1.1. JVM記憶體模型總體架構圖 1 1.2. JAVA堆 2 1.3. 方法區 元空間(Metaspace) 2 1.4. 虛擬機器棧 3 1.5. 本地方法區 4 2. 垃圾回收演算法 4 2

目錄

1.1. JVM記憶體模型總體架構圖 1

1.2. JAVA堆 2

1.3. 方法區 元空間(Metaspace) 2

1.4. 虛擬機器棧 3

1.5. 本地方法區 4

2. 垃圾回收演算法 4

2.1. 標記-清除演算法(Mark-Sweep) 4

2.2. 複製演算法(copying) 4

2.3. 標記-壓縮演算法(Mark-compact) 5

3. JVM引數: 6

4. 檢視工具 7

4.1. jconsole.exe 7

4.2. D:\jdk1.8.0_31\bin\jvisualvm.exe 8

5. ref 8

 

    1. JVM記憶體模型總體架構圖

 

 

    1. JAVA堆


執行緒共享的,存放所有物件例項和陣列。垃圾回收的主要區域。可以分為新生代和老年代(tenured)。
新生代用於存放剛建立的物件以及年輕的物件,如果物件一直沒有被回收,生存得足夠長,老年物件就會被移入老年代。
新生代又可進一步細分為eden、survivorSpace0(s0,from space)、survivorSpace1(s1,to space)。剛建立的物件都放入eden,s0和s1都至少經過一次GC並倖存。如果倖存物件經過一定時間仍存在,則進入老年代(tenured)。

    1. 方法區 元空間(Metaspace)

 


執行緒共享的,用於存放被虛擬機器載入的類的元資料資訊:如常量、靜態變數、即時編譯器編譯後的程式碼。也成為永久代。如果hotspot虛擬機器確定一個類的定義資訊不會被使用,也會將其回收。回收的基本條件至少有:所有該類的例項被回收,而且裝載該類的ClassLoader被回收

 

元空間(Metaspace)

3.1元空間的記憶體大小

元空間是方法區的在HotSpot jvm 中的實現,方法區主要用於儲存類的資訊、常量池、方法資料、方法程式碼等。方法區邏輯上屬於堆的一部分,但是為了與堆進行區分,通常又叫“非堆”。

元空間的本質和永久代類似,都是對JVM規範中方法區的實現。不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機器中,而是使用本地記憶體。,理論上取決於32位/64位系統可虛擬的記憶體大小。可見也不是無限制的,需要配置引數。

根據上面的各種原因,永久代最終被移除,方法區移至Metaspace,字串常量移至Java Heap

隨著JDK8的到來,JVM不再有PermGen。但類的元資料資訊(metadata)還在,只不過不再是儲存在連續的堆空間上,而是移動到叫做“Metaspace”的本地記憶體(Native memory)中。

 

 

 

程式計數器
多執行緒時,當執行緒數超過CPU數量或CPU核心數量,執行緒之間就要根據時間片輪詢搶奪CPU時間資源。因此每個執行緒有要有一個獨立的程式計數器,記錄下一條要執行的指令。執行緒私有的記憶體區域。如果執行的是JAVA方法,計數器記錄正在執行的java位元組碼地址,如果執行的是native方法,則計數器為空。

    1. 虛擬機器棧


執行緒私有的,與執行緒在同一時間建立。管理JAVA方法執行的記憶體模型。每個方法執行時都會建立一個楨棧來儲存方法的的變量表、運算元棧、動態連結方法、返回值、返回地址等資訊。棧的大小決定了方法呼叫的可達深度(遞迴多少層次,或巢狀呼叫多少層其他方法,-Xss引數可以設定虛擬機器棧大小)。棧的大小可以是固定的,或者是動態擴充套件的。如果請求的棧深度大於最大可用深度,則丟擲stackOverflowError;如果棧是可動態擴充套件的,但沒有記憶體空間支援擴充套件,則丟擲OutofMemoryError。
使用jclasslib工具可以檢視class類檔案的結構。下圖為棧幀結構圖:

 

 

    1. 本地方法區


和虛擬機器棧功能相似,但管理的不是JAVA方法,是本地方法,本地方法是用C實現的。

 

  1. 垃圾回收演算法
    1. 標記-清除演算法(Mark-Sweep)

從根節點開始標記所有可達物件,其餘沒標記的即為垃圾物件,執行清除。但回收後的空間是不連續的。
 

    1. 複製演算法(copying)


將記憶體分成兩塊,每次只使用其中一塊,垃圾回收時,將標記的物件拷貝到另外一塊中,然後完全清除原來使用的那塊記憶體。複製後的空間是連續的。複製演算法適用於新生代,因為垃圾物件多於存活物件,複製演算法更高效。在新生代序列垃圾回收演算法中,將eden中標記存活的物件拷貝未使用的s1中,s0中的年輕物件也進入s1,如果s1空間已滿,則進入老年代;這樣交替使用s0和s1。這種改進的複製演算法,既保證了空間的連續性,有避免了大量的記憶體空間浪費。

 

    1. 標記-壓縮演算法(Mark-compact)


適合用於老年代的演算法(存活物件多於垃圾物件)。
標記後不復制,而是將存活物件壓縮到記憶體的一端,然後清理邊界外的所有物件。

 

 


 

  1. JVM引數:

 

-XX:+PrintGCDetails  列印垃圾回收資訊

-Xms 為Heap區域的初始值,線上環境需要與-Xmx設定為一致,否則capacity的值會來回飄動
-Xmx 為Heap區域的最大值
-Xss(或-ss) 執行緒棧大小(指一個執行緒的native空間)1.5以後是1M的預設大小
-XX:PermSize與-XX:MaxPermSize  方法區(永久代)的初始大小和最大值(但不是本地方法區)
-XX:NewRatio  老年代與新生代比率
-XX:SurvivorRatio  Eden與Survivor的佔用比例。例如8表示,一個survivor區佔用 1/8 的Eden記憶體,即1/10的新生代記憶體,為什麼不是1/9?因為我們的新生代有2個survivor,即S1和S22。所以survivor總共是佔用新生代記憶體的 2/10,Eden與新生代的佔比則為 8/10。
-XX:MaxHeapFreeRatio  GC後,如果發現空閒堆記憶體佔到整個預估的比例小於這個值,則減小堆空間。
-XX:MinHeapFreeRatio  GC後,如果發現空閒堆記憶體佔到整個預估的比例大於這個值,則增大堆空間。
-XX:NewSize    新生代大小

 

 

  1. 檢視工具
    1. jconsole.exe

 

 

 

 

    1. D:\jdk1.8.0_31\bin\jvisualvm.exe

 

  1. ref

 

JDK8-廢棄永久代(PermGen)迎來元空間(Metaspace) - 只會一點java - 部落格園.html