jdk1.8——jvm分析與調優

不少文章都是講如何配置JVM各個參數的,可是生產環境裏參數的值到底配置爲多少,卻沒有一個具體的指標。文章分四個部分,分別是JVM說明、配置,GC的過程和具體配置值。css


一.JVM空間說明

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

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

 
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異常。jvm

  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。spa

三.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。code

四. JVM參數配置指南

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

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

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

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

按照Java官方的指導

 

 
image.png
  • 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
相關文章
相關標籤/搜索