不少文章都是講如何配置JVM各個參數的,可是生產環境裏參數的值到底配置爲多少,卻沒有一個具體的指標。文章分四個部分,分別是JVM說明、配置,GC的過程和具體配置值。css
JDK 1.7及之前,Java 類信息、常量池、靜態變量都存儲在 Perm(永久代)裏。類的元數據和靜態變量在類加載的時候分配到 Perm,當類被卸載的時候垃圾收集器從 Perm 處理掉。apache
JDK 1.8 的對 JVM 架構的改造將類元數據放到本地內存中,另外,將常量池和靜態變量放到 Java 堆裏。HotSopt VM 將會爲類的元數據明確分配和釋放本地內存。在這種架構下,類元信息就突破了原來 -XX:MaxPermSize 的限制,因此PermSize的配置也是無效的,如今可使用更多的本地內存。這樣就從必定程度上解決了原來在運行時生成大量類的形成常常 Full GC 問題,如運行時使用反射、代理等bash
乾貨:能夠發現最明顯的一個變化是元空間從虛擬機轉移到本地內存;默認狀況下,元空間的大小僅受本地內存的限制。這意味着之後不會由於永久代空間不夠而拋出OOM異常了。
jdk1.8之前版本的class和jar包數據存儲在permGen下面 ,permGen大小是固定的,並且項目之間沒法共用公有的class,因此很容易碰到OOM異常。
改爲metaSpaces後,各個項目會共享一樣的class內存空間,好比多個項目都引用了apache-common包,在metaSpaces中只會存儲一份apache-common的class,提升了內存的利用率,垃圾回收更有效率。架構
-XX:PermSize=512M -XX:MaxPermSize=1024M
表示在JVM裏存儲Java類信息,常量池和靜態變量的永久代區域初始大小爲512M,最大爲1024M。在項目啓動後,這個值是固定的,若是項目class過多,極可能遇到OutOfMemoryError: PermGen
異常。jvm
-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的過程再合適不過。代理
清理Eden區和Survivor區叫Minor GC;清理Old區叫Major GC;清理整個堆空間—包括年輕代和老年代叫Full GC。code
前面三個部分對JVM進行了總體的瞭解,接下來是本文的重點。orm
-XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -Xms256m -Xmx256m
文章看下來上面這段配置的意思很簡單,設置元空間的初始值和最大值,設置堆空間的初始值和最大值。
爲何MetaspaceSize要設置爲128M?爲何堆內存初始值Xms設置爲256M而不是512M?
按照Java官方的指導
可讓系統運行一段時間後查看系統的各個指標,而後在進行配置。以下用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