JVM簡介堆中新生代老年代淺析

一、JVM內存結構由程序計數器、堆、棧、本地方法棧、方法區等部分組成。
1)程序計數器
幾乎不佔有內存。用於取下一條執行的指令。
2)堆
所有通過new創建的對象的內存都在堆中分配,其大小可以通過-Xmx和-Xms來控制。堆被劃分爲新生代和舊生代,新生代又被進一步劃分爲Eden和Survivor區,最後Survivor由FromSpace和ToSpace組成。
一般情況將新生代分爲Eden ,兩塊Survivor區域;
新生代。新建的對象都是用新生代分配內存,Eden空間不足的時候,會把存活的對象轉移到Survivor中,新生代大小可以由-Xmn來控制,也可以用-XX:SurvivorRatio來控制Eden和Survivor的比例舊生代。用於存放新生代中經過多次垃圾回收仍然存活的對象。
3)棧
每個線程執行每個方法的時候都會在棧中申請一個棧幀,每個棧幀包括局部變量區和操作數棧,用於存放此次方法調用過程中的臨時變量、參數和中間結果。
4)本地方法棧
用於支持native方法的執行,存儲了每個native方法調用的狀態。
5)方法區
存放了要加載的類信息、靜態變量、final類型的常量、屬性和方法信息。JVM用永久代(PermanetGeneration)來存放方法區,(在JDK的HotSpot虛擬機中,可以認爲方法區就是永久代,但是在其他類型的虛擬機中,沒有永久代的概念,有關信息可以看周志明的書)可通過-XX:PermSize和-XX:MaxPermSize來指定最小值和最大值。

二、JVM垃圾回收機制
JVM分別對新生代和舊生代採用不同的垃圾回收機制
新生代的GC:
新生代通常存活時間較短,因此基於複製算法來進行回收,所謂複製算法就是掃描出存活的對象,並複製到一塊新的完全未使用的空間中,對應於新生代,就是在Eden和其中一個Survivor,複製到另一個之間Survivor空間中,然後清理掉原來就是在Eden和其中一個Survivor中的對象。新生代採用空閒指針的方式來控制GC觸發,指針保持最後一個分配的對象在新生代區間的位置,當有新的對象要分配內存時,用於檢查空間是否足夠,不夠就觸發GC。當連續分配對象時,對象會逐漸從eden到 survivor,最後到老年代。

用javavisualVM來查看,能明顯觀察到新生代滿了後,會把對象轉移到舊生代,然後清空繼續裝載,當舊生代也滿了後,就會報outofmemory的異常。

舊生代與新生代不同,對象存活的時間比較長,比較穩定,因此採用標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,然後再進行回收未被標記的對象,回收後對用空出的空間要麼進行合併,要麼標記出來便於下次進行分配,總之就是要減少內存碎片帶來的效率損耗。

三、GC堆

Java 中的堆是 JVM 所管理的最大的一塊內存空間,主要用於存放各種類的實例對象。
在 Java 中,堆被劃分成兩個不同的區域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被劃分爲三個區域:Eden、From Survivor、To Survivor。
這樣劃分的目的是爲了使 JVM 能夠更好的管理堆內存中的對象,包括內存的分配以及回收。
堆的內存模型大致爲:


從圖中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通過參數 –Xms、-Xmx 來指定。
默認的,新生代 ( Young ) 與老年代 ( Old ) 的比例的值爲 1:2 ( 該值可以通過參數 –XX:NewRatio 來指定),即:新生代 ( Young ) = 1/3 的堆空間大小。老年代 ( Old ) = 2/3 的堆空間大小。其中,新生代 ( Young )被細分爲 Eden 和 兩個 Survivor 區域,這兩個 Survivor 區域分別被命名爲 from 和 to,以示區分。
默認的,Edem : from : to = 8 :1 : 1 ( 可以通過參數–XX:SurvivorRatio 來設定 ),即: Eden = 8/10 的
新生代空間大小,from = to = 1/10 的新生代空間大小。
JVM 每次只會使用 Eden 和其中的一塊 Survivor 區域來爲對象服務,所以無論什麼時候,總是有一塊Survivor區域是空閒着的。
因此,新生代實際可用的內存空間爲 9/10 ( 即90% )的新生代空間。

四、JVM 參數選項 
下面只列舉其中的幾個常用和容易掌握的配置選項:
-Xms
初始堆大小。如:-Xms256m

-Xmx
最大堆大小。如:-Xmx512m

-Xmn
新生代大小。通常爲 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 個 Survivor 空間。實際可用空間爲 = Eden + 1 個 Survivor,即 90%

-Xss
JDK1.5+ 每個線程堆棧大小爲 1M,一般來說如果棧不是很深的話, 1M 是絕對夠用了的。

-XX:NewRatio
新生代與老年代的比例,如 –XX:NewRatio=2,則新生代佔整個堆空間的1/3,老年代佔2/3

-XX:SurvivorRatio
新生代中 Eden 與 Survivor 的比值。默認值爲 8。即 Eden 佔新生代空間的 8/10,另外兩個 Survivor 各佔 1/10

-XX:PermSize
永久代(方法區)的初始大小

-XX:MaxPermSize
永久代(方法區)的最大值

-XX:+PrintGCDetails
打印 GC 信息

-XX:+HeapDumpOnOutOfMemoryError
讓虛擬機在發生內存溢出時 Dump 出當前的內存堆轉儲快照,以便分析用

發佈了65 篇原創文章 · 獲贊 26 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章