圖解JVM記憶體模型
/**
* 轉載請註明作者longdick http://longdick.iteye.com
*
*/
Java 的記憶體模型由3個代組成,各個代的預設排列有如下圖(適用JDK1.4.* 到 JDK6):
Java 的記憶體模型分為
Young(年輕代)
Tenured(終身代)
Perm(永久代)
有些舊版本也叫作
New
Old
Perm
叫法不同,表達的意思卻是基本相同。
注意Young(年輕代)還可以分為Eden區和兩個Survivor區(from和to,這兩個Survivor區大小嚴格一至),新的物件例項總是首先放在Eden區,Survivor區作為Eden區和
Tenure(終生代)中存放生命週期長久的例項物件,但並不是如它的名字那樣是終生的,裡面的物件照樣會被回收掉。
Young和Tenure共同組成了堆記憶體。
Perm(永久代)則是非堆記憶體的組成部分。主要存放載入的Class類級物件如class本身,method,field等等。
有同學可能已經注意到了,每個代都有的Virtual區又是什麼?
我們知道有一些引數可以影響以上各代的大小。
在JVM啟動時,就已經保留了固定的記憶體空間給Heap記憶體,這部分記憶體並不一定都會被JVM使用,但是可以確定的是這部分保留的記憶體不會被其他程序使用。這部分記憶體大小由 -Xmx
而另一部分記憶體在JVM啟動時就分配給JVM,作為JVM的初始Heap記憶體使用。影響這個的引數是 -Xms ,如果 -Xms 指定的值比-Xmx 的小,那麼兩者的差值就是Virtual記憶體值。隨著程式的執行,Eden區、 Tenured區和Perm區會逐漸使用保留的Virtual空間。
如果沒有具體指定,初始和最大堆記憶體將根據機器的記憶體計算得出。引數DefaultInitialRAMFraction
和DefaultMaxRAMFraction
會影響最終的結果,如下表所示:
Formula Default
initial heap size | memory / DefaultInitialRAMFraction |
memory / 64 |
maximum heap size | MIN(memory / DefaultMaxRAMFraction, 1GB) |
MIN(memory / 4, 1GB) |
可以看到堆記憶體預設值最大不會超過1G。
JVM會根據堆記憶體的使用情況自動決定何時擴張和縮減實際堆記憶體的大小,可以用VM引數-XX:MinHeapFreeRatio=<minimum>
和 -XX:MaxHeapFreeRatio=<maximum>
使用堆記憶體空閒百分比來定義,一般在32位機器上的預設值如下:
MinHeapFreeRatio |
40 |
MaxHeapFreeRatio |
70 |
-Xms |
3670k |
-Xmx |
64m |
當空閒堆記憶體所佔堆記憶體百分比低於40%,JVM就會試圖擴張堆記憶體空間;當空閒堆記憶體所佔堆記憶體百分比高於70%,JVM就會試圖壓縮堆記憶體空間。
ps:以上預設值在不同平臺會有不同的值,如果是64位系統,這些值一般需要擴張30%,來容納在64位系統下變大的物件。
加上-XX:NewRatio=3
意味著 young(年輕代) 和 tenured(終生代)的比率是1:3,也就是說,eden區和survivor區容量之和將佔總堆記憶體的1/4。
加上-XX:SurvivorRatio=6
設定eden區和 其中一個survivor space的比率是1:6,也就是說,其中一個survivor space佔年輕代1/8的容量 (可以想想為什麼不是1/7)。
另外還有 -XX:NewSize
-XX:MaxNewSize 指定年輕代的初始值和最大值。
32位系統下預設值如下:
Default Value Parameter Client JVM Server JVM
NewRatio |
8 |
2 |
NewSize |
2228K |
2228K |
MaxNewSize |
not limited |
not limited |
SurvivorRatio |
32 |
32 |
延伸閱讀:
參考資料:
http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html