jvm的內存模型
jvm的內存模型在1.7和1.8有較大的區別,雖然本套課程是以1.8爲例進行講解,但是我們也是需要對1.7的內存模
型有所瞭解,所以接下里,我們將先學習1.7再學習1.8的內存模型。
jdk1.7的堆內存模型
-
Young 年輕區(代)
Young區被劃分爲三部分,Eden區和兩個大小嚴格相同的Survivor區,其中,Survivor區間中,某一時刻只有其中一個是被使用的,另外一個留做垃圾收集時複製對象用,在Eden區間變滿的時候, GC就會將存活的對象移到空閒的Survivor區間中,根據JVM的策略,在經過幾次垃圾收集後,任然存活於Survivor的對象將被移動到Tenured區間。 -
Tenured 年老區
Tenured區主要保存生命週期長的對象,一般是一些老的對象,當一些對象在Young複製轉移一定的次數以後,對象就會被轉移到Tenured區,一般如果系統中用了application級別的緩存,緩存中的對象往往會被轉移到這一區間。 -
Perm 永久區
Perm代主要保存class,method,filed對象,這部份的空間一般不會溢出,除非一次性加載了很多的類,不過在涉及到熱部署的應用服務器的時候,有時候會遇到java.lang.OutOfMemoryError : PermGen space 的錯誤,造成這個錯誤的很大原因就有可能是每次都重新部署,但是重新部署後,類的class沒有被卸載掉,這樣就造成了大量的class對象保存在了perm中,這種情況下,一般重新啓動應用服務器可以解決問題。 -
Virtual區:
最大內存和初始內存的差值,就是Virtual區。
jdk1.8的堆內存模型
由上圖可以看出,jdk1.8的內存模型是由2部分組成,年輕代 + 年老代。
年輕代:Eden + 2*Survivor
年老代:OldGen
在jdk1.8中變化最大的Perm區,用Metaspace(元數據空間)進行了替換。
需要特別說明的是:Metaspace所佔用的內存空間不是在虛擬機內部,而是在本地內存空間中,這也是與1.7的永久代最大的區別所在。
爲什麼要廢棄1.7中的永久區?
官網給出瞭解釋:http://openjdk.java.net/jeps/122
移除永久代是爲融合HotSpot JVM與 JRockit VM而做出的努力,因爲JRockit沒有永久代,不需要配置永久代。
現實使用中,由於永久代內存經常不夠用或發生內存泄露,爆出異常java.lang.OutOfMemoryError: PermGen。
基於此,將永久區廢棄,而改用元空間,改爲了使用本地內存空間。
通過jstat命令進行查看堆內存使用情況
jstat命令可以查看堆內存各部分的使用量,以及加載類的數量。命令的格式如下:
jstat [-命令選項] [vmid] [間隔時間/毫秒] [查詢次數]
查看class加載統計
說明:
- Loaded:加載class的數量
- Bytes:所佔用空間大小
- Unloaded:未加載數量
- Bytes:未加載佔用空間
- Time:時間
查看編譯統計
說明:
- Compiled:編譯數量。
- Failed:失敗數量
- Invalid:不可用數量
- Time:時間
- FailedType:失敗類型
- FailedMethod:失敗的方法