https://blog.csdn.net/qq_3253...java
內存區域劃分算法
限定商用虛擬機基本都採用分代收集算法進行垃圾回收。根據對象的生命週期的不一樣將內存劃分爲幾塊,而後根據各塊的特色採用最適當的收集算法。大批對象死去、少許對象存活的,使用複製算法,複製成本低;對象存活率高、沒有額外空間進行分配擔保的,採用標記-清除算法或者標記-整理算法。緩存
從上面的圖能夠看出, JVM區域整體分兩類,heap區和非heap區。 併發
1.heap區又分爲: spa
2.非heap區又分: .net
關於java堆,新生代,老年代,Eden空間,From Survivor空間,To Survivor空間
java進程運行過程當中建立的對象存放在堆中,堆被劃分紅兩個不一樣的區域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被劃分爲三個區域:Eden、From Survivor、To Survivor。
堆的內存模型大體爲: server
默認的,新生代 ( 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% )的新生代空間。對象
新生代是 GC 收集垃圾的頻繁區域。
當對象在 Eden ( 包括一個 Survivor 區域,這裏假設是 from 區域 ) 出生後,在通過一次 Minor GC 後,若是對象還存活,而且可以被另一塊 Survivor 區域所容納
( 上面已經假設爲 from 區域,這裏應爲 to 區域,即 to 區域有足夠的內存空間來存儲 Eden 和 from 區域中存活的對象 ),則使用複製算法將這些仍然還存活的對象複製到另一塊 Survivor 區域 ( 即 to 區域 ) 中,而後清理所使用過的 Eden 以及 Survivor 區域 ( 即 from 區域 ),而且將這些對象的年齡設置爲1,之後對象在 Survivor 區每熬過一次 Minor GC,就將對象的年齡 + 1,當對象的年齡達到某個值時 ( 默認是 15 歲,能夠經過參數 -XX:MaxTenuringThreshold 來設定 ),這些對象就會成爲老年代。
但這也不是必定的,對於一些較大的對象 ( 即須要分配一塊較大的連續內存空間 ) 則是直接進入到老年代。blog
From Survivor區域與To Survivor區域是交替切換空間,在同一時間內二者中只有一個不爲空 生命週期
2.內存區域介紹
1.年輕代:
HotSpot JVM把年輕代分爲了三部分:1個Eden區和2個Survivor區(分別叫from和to)。默認比例爲8:1,爲啥默認會是這個比例,接下來咱們會聊到。通常狀況下,新建立的對象都會被分配到Eden區(一些大對象特殊處理),這些對象通過第一次Minor GC後,若是仍然存活,將會被移到Survivor區。對象在Survivor區中每熬過一次Minor GC,年齡就會增長1歲,當它的年齡增長到必定程度時,就會被移動到年老代中。
由於年輕代中的對象基本都是朝生夕死的(80%以上),因此在年輕代的垃圾回收算法使用的是複製算法,複製算法的基本思想就是將內存分爲兩塊,每次只用其中一塊,當這一塊內存用完,就將還活着的對象複製到另一塊上面。複製算法不會產生內存碎片。
在GC開始的時候,對象只會存在於Eden區和名爲「From」的Survivor區,Survivor區「To」是空的。緊接着進行GC,Eden區中全部存活的對象都會被複制到「To」,而在「From」區中,仍存活的對象會根據他們的年齡值來決定去向。年齡達到必定值(年齡閾值,能夠經過-XX:MaxTenuringThreshold來設置)的對象會被移動到年老代中,沒有達到閾值的對象會被複制到「To」區域。通過此次GC後,Eden區和From區已經被清空。這個時候,「From」和「To」會交換他們的角色,也就是新的「To」就是上次GC前的「From」,新的「From」就是上次GC前的「To」。無論怎樣,都會保證名爲To的Survivor區域是空的。Minor GC會一直重複這樣的過程,直到「To」區被填滿,「To」區被填滿以後,會將全部對象移動到年老代中。
有關年輕代的JVM參數
1)-XX:NewSize和-XX:MaxNewSize
用於設置年輕代的大小,建議設爲整個堆大小的1/3或者1/4,兩個值設爲同樣大。
2)-XX:SurvivorRatio
用於設置Eden和其中一個Survivor的比值,這個值也比較重要。
3)-XX:+PrintTenuringDistribution
這個參數用於顯示每次Minor GC時Survivor區中各個年齡段的對象的大小。
4).-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold
用於設置晉升到老年代的對象年齡的最小值和最大值,每一個對象在堅持過一次Minor GC以後,年齡就加1。
2.old老年代
老年代,用於存放新生代中通過屢次垃圾回收仍然存活的對象,也有多是新生代分配不了內存的大對象會直接進入老年代。通過屢次垃圾回收都沒有被回收的對象,這些對象的年代已經足夠old了,就會放入到老年代。
當老年代被放滿的以後,虛擬機會進行垃圾回收,稱之爲Major GC。因爲Major GC除併發GC外均需對整個堆進行掃描和回收,所以又稱爲Full GC。
heap區即堆內存,整個堆大小=年輕代大小 + 老年代大小。堆內存默認爲物理內存的1/64(<1GB);默認空餘堆內存小於40%時,JVM就會增大堆直到-Xmx的最大限制,能夠經過MinHeapFreeRatio參數進行調整;默認空餘堆內存大於70%時,JVM會減小堆直到-Xms的最小限制,能夠經過MaxHeapFreeRatio參數進行調整。
3.Code Cache代碼緩存區
它主要用於存放JIT所編譯的熱點代碼。CodeCache代碼緩衝區的大小在client模式下默認最大是32m,在server模式下默認是48m,這個值也是能夠設置的,它所對應的JVM參數爲ReservedCodeCacheSize 和 InitialCodeCacheSize,能夠經過以下的方式來爲Java程序設置。
-XX:ReservedCodeCacheSize=128m
1
CodeCache緩存區是可能被充滿的,當CodeCache滿時,後臺會收到CodeCache is full的警告信息,以下所示:
「CompilerThread0」 java.lang.OutOfMemoryError: requested 2854248 bytes for Chunk::new. Out of swap space?
4.Perm Gen(永久代) (JDK1.8以後被元空間替代)
Perm Gen全稱是Permanent Generation space,稱之爲永久代,其實指的就是這個方法區。不過方法區和「PermGen space」又有着本質的區別。前者是 JVM 的規範,然後者則是 JVM 規範的一種實現,而且只有 HotSpot 纔有 「PermGen space」,而對於其餘類型的虛擬機,如 JRockit(Oracle)、J9(IBM) 並無「PermGen space」。
因爲方法區主要存儲類的相關信息,Class在被Load進入這個區域後,若是應用程序LOAD不少Class的話,就極可能會出現PermGen space錯誤,好比對於動態生成類的狀況比較容易出現永久代的內存溢出。它的默認大小爲物理內存的1/64。
————————————————
版權聲明:本文爲CSDN博主「xk_一步一步來」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/qq_3253...