jdk1.8——jvm分析與調優

一.JVM空間說明

  1. JDK 1.7及以前,Java 類信息、常量池、靜態變量都存儲在 Perm(永久代)裏。類的元數據和靜態變量在類加載的時候分配到 Perm,當類被卸載的時候垃圾收集器從 Perm 處理掉。

  2. JDK 1.8 的對 JVM 架構的改造將類元數據放到本地內存中,另外,將常量池靜態變量放到 Java 堆裏。HotSopt VM 將會爲類的元數據明確分配和釋放本地內存。在這種架構下,類元信息就突破了原來 -XX:MaxPermSize 的限制,所以PermSize的配置也是無效的,現在可以使用更多的本地內存。這樣就從一定程度上解決了原來在運行時生成大量類的造成經常 Full GC 問題,如運行時使用反射、代理等

jvm內存

乾貨:可以發現最明顯的一個變化是元空間從虛擬機轉移到本地內存;默認情況下,元空間的大小僅受本地內存的限制。這意味着以後不會因爲永久代空間不夠而拋出OOM異常了。
jdk1.8以前版本的class和jar包數據存儲在permGen下面 ,permGen大小是固定的,而且項目之間無法共用公有的class,所以很容易碰到OOM異常。
改成metaSpaces後,各個項目會共享同樣的class內存空間,比如多個項目都引用了apache-common包,在metaSpaces中只會存儲一份apache-common的class,提高了內存的利用率,垃圾回收更有效率。

二.JVM參數配置

  1. 在jdk1.8以前,生產環境一般有如下配置
-XX:PermSize=512M -XX:MaxPermSize=1024M

表示在JVM裏存儲Java類信息,常量池和靜態變量的永久代區域初始大小爲512M,最大爲1024M。在項目啓動後,這個值是固定的,如果項目class過多,很可能遇到OutOfMemoryError: PermGen異常。

  1. 升級JDK1.8之後,上面的perm配置已經變成
-XX:MetaspaceSize=512M XX:MaxMetaspaceSize=1024M

MetaspaceSize如果不做配置,通過jinfo查看默認MetaspaceSize大小(約21M),MaxMetaspaceSize很大很大,前面說過MetaSpace只受本地內存大小限制。

jinfo -flag MetaspaceSize 1234  #結果爲:-XX:MetaspaceSize=21807104
jinfo -flag MaxMetaspaceSize 1234 #結果爲:-XX:MaxMetaspaceSize=18446744073709547520

乾貨:MetaspaceSize爲出發FullGC的閾值,默認約爲21M,如做了配置,最小閾值爲自定義配置大小。空間使用達到閾值,觸發FullGC,同時對該值擴大。當然如果元空間實際使用小於閾值,在GC的時候也會對該值縮小。
MaxMetaspaceSize爲元空間的最大值,如果設置太小,可能會導致頻繁FullGC,甚至OOM。

三.GC(GarbageCollection)過程

首先貼一張網上盜來的大圖,用它來說明下GC的過程再合適不過。

 

image.png

  1. 新new的對象都放在Eden區(伊甸園嘛,創造的地方
  2. Eden區滿或者快滿的時候進行一次清理(Minor Gc),不被引用的對象直接被幹掉;還有引用的對象,但是年齡比較大的,挪到S0區
  3. 下次Eden區快滿的時候,會進行上一步的操作,並且將Eden和S0區的年紀大的對象放到S1區【原理上隨時保持S0和S1有一個是空的,用來存下一次的對象】
  4. 下下次,Eden區快滿的時候,會進行上一步操作,並且將Eden和S1區的年紀大的對象放到S0區【此時S1區就是空的】
  5. 直到Eden區快滿,S0或者S1也快滿的時候,這時候就把這兩個區的年紀大的對象放到Old區
  6. 依次循環,直到Old區也快滿的時候,Eden區也快滿的時候,會對整個這一塊內存區域進行一次大清洗(FullGC),騰出內存,爲之後的對象創建,程序運行騰地方。

清理Eden區和Survivor區叫Minor GC;清理Old區叫Major GC;清理整個堆空間—包括年輕代和老年代叫Full GC

四. JVM參數配置指南

前面三個部分對JVM進行了整體的瞭解,接下來是本文的重點。

 

-XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -Xms256m -Xmx256m

文章看下來上面這段配置的意思很簡單,設置元空間的初始值和最大值,設置堆空間的初始值和最大值。

爲什麼MetaspaceSize要設置爲128M?爲什麼堆內存初始值Xms設置爲256M而不是512M?

按照Java官方的指導

Java堆大小設置,Xms 和 Xmx設置爲老年代存活對象的3-4倍,即FullGC之後的老年代內存佔用的3-4倍
永久代 PermSize和MaxPermSize(元空間)設置爲老年代存活對象的1.2-1.5倍。
年輕代Xmn的設置爲老年代存活對象的1-1.5倍。
老年代的內存大小設置爲老年代存活對象的2-3倍。

 

可以讓系統運行一段時間後查看系統的各個指標,然後在進行配置。如下用jstat工具查看jvm的情況

jstat -gc 12345
###
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
13824.0 22528.0 13377.0  0.0   548864.0 535257.2  113152.0   46189.3   73984.0 71119.8 9728.0 9196.2     14    0.259   3      0.287    0.546

OU表示老年代所佔用的內存爲 46189.3 K(大約45M);那麼jvm相應的配置參數應該做如下修改

-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M -Xms180m -Xmx180m

 

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