JVM_堆

Java 中的堆是 JVM 管理的最大的一塊內存空間,主要用於存放Java類的實例對象,其被劃分爲兩個不同的區域:新生代 ( Young )和老年代 ( Old ),其中新生代 ( Young ) 又被劃分爲:EdenFrom SurvivorTo Survivor三個區域。

我們可以通過一段簡單的代碼來查看堆的空間劃分。

public class Jtest {
		public static void main(String[] args) {
			System.out.println("Hello,JVM!");
		}
}

右鍵選擇 run configuration

再如下的地方添加 -Xms1024m -Xmx1024m -XX:+PrintGCDetails 代碼

控制檯輸出:

 可以看出上面有幾個未知的單詞。而這幾個單詞正是代表了 堆的內存空間。

Java 中的堆是 JVM 管理的最大的一塊內存空間,主要用於存放Java類的實例對象,其被劃分爲兩個不同的區域:新生代 ( Young )和老年代 ( Old ),其中新生代 ( Young ) 又被劃分爲:EdenFrom Survivor To Survivor三個區域

JDK8開始,Metaspace(元空間)替代了永久代,如下圖所示:

 

無論哪個版本的JDK,其堆內存的劃分都沒有變化,下面詳述Java堆中各個區域:

1、堆大小 = 新生代( Young )  + 老年代( Old ),其可以通過參數 –Xms-Xmx 來指定:–Xms用於設置初始分配大小,默認爲物理內存的1/16-Xmx用於設置最大分配內存,默認爲物理內存的1/4。默認情況下,新生代 ( Young ) 與老年代 ( Old ) 的比例的值爲 1:2 ,即:新生代 ( Young ) = 1/3 的堆空間大小,老年代 ( Old ) = 2/3 的堆空間大小

2、新生代 ( Young ) 被細分爲 Eden 兩個 Survivor 區域,爲了便於區分,兩個 Survivor 區域分別被命名爲 from to。默認情況下,Eden : from : to = 8 : 1 : 1 ,即: Eden = 8/10 的新生代空間大小,from = to = 1/10 的新生代空間大小。JVM 每次只使用 Eden 和其中的一塊 Survivor 區域來爲對象服務,所以無論什麼時候,總是有一塊 Survivor 區域是空閒着的,因此,新生代實際可用的內存空間爲 9/10 ( 90% )的新生代空間。

3 、工作原理:

 

aEden區爲Java對象分配堆內存,當 Eden 區沒有足夠空間分配時,JVM發起一次Minor GC,將Eden區仍然存活的對象放入Survivor from區,並清空Eden 區;

bEden區被清空後,繼續爲新的Java對象分配堆內存;

c、當Eden區再次沒有足夠空間分配時,JVMEden區和Survivor from區同時發起一次 Minor GC,把存活對象放入Survivor to區,同時清空Eden 區和Survivor from區;

dEden區繼續爲新的Java對象分配堆內存,並重覆上述過程:Eden區沒有足夠空間分配時,把Eden區和某個Survivor區的存活對象放到另一個Survivor區;

eJVM給每個對象設置了一個對象年齡(Age)計數器,每熬過一場Minor GC,對象年齡增加1歲,當它的年齡增加到閾值(默認爲15),將被晉升到老年代,當 Old 區也被填滿時,JVM發起一次 Major GC,對 Old 區進行垃圾回收。

 

我們可以使用java 自帶的 java visualvm 來直觀的觀察 堆內存

 

我們首先打開visualvm 進行配置 工具-> 插件

然後我們去改一下插件下載地址。Java VisualVM默認的插件中心網址已關閉服務,插件中心的服務器已經移交到github上,地址爲https://visualvm.github.io/pluginscenters.html 去github 上尋找符合自己版本的下載地址粘貼上去。

 更新好之後我們去可用插件中找VisualGC 下載。

 

然後我們啓動一個線程 並回到 java visualvm 打開GC 觀察

 再圖中我們可以清晰的看到 Eden s0 s1 與 Old 的內存變化

 

 

 

 

 

 

 

 

 

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