jvm監控、優化及問題排查思路

從經驗總結來看jvm參數設計原則爲html

1、內存分配佔比java

當服務器比較純粹,只有JAVA服務,沒有其它如監控、代理等第三方服務且本服務網絡IO不大的時候,能夠將jvm內存分配佔系統內存2/3左右,可是在互聯網公司一般都會作微服務化,爲了監控系統狀態、日誌收集、實時報警等服務會佔用系統比較多的內存,此時jvm內存分配佔系統存應當在1/2如下。性能優化

2、參數配置服務器

jvm的最大內存與最小內存設爲同樣,避名內存重分配形成的性能損耗網絡

生產環境一般內存分配會比較大,對應用暫時時間有要求可採用G1回收器(G1與CMS回收器 區別多線程

評估和微調 G1 GC 時,請記住如下建議:併發

  • 年輕代大小:避免使用 -Xmn 選項或 -XX:NewRatio 等其餘相關選項顯式設置年輕代大小。固定年輕代的大小會覆蓋暫停時間目標。
  • 暫停時間目標:每當對垃圾回收進行評估或調優時,都會涉及到延遲與吞吐量的權衡。G1 GC 是增量垃圾回收器,暫停統一,同時應用程序線程的開銷也更多。G1 GC 的吞吐量目標是 90% 的應用程序時間和 10%的垃圾回收時間。若是將其與 Java HotSpot VM 的吞吐量回收器相比較,目標則是 99% 的應用程序時間和 1% 的垃圾回收時間。所以,當您評估 G1 GC 的吞吐量時,暫停時間目標不要太嚴苛。目標太過嚴苛表示您願意承受更多的垃圾回收開銷,而這會直接影響到吞吐量。當您評估 G1 GC 的延遲時,請設置所需的(軟)實時目標,G1 GC 會盡可能知足。反作用是,吞吐量可能會受到影響。
  • 掌握混合垃圾回收:當您調優混合垃圾回收時,請嘗試如下選項。
     
    • -XX:InitiatingHeapOccupancyPercent
      用於更改標記閾值。
    • -XX:G1MixedGCLiveThresholdPercent 和 -XX:G1HeapWastePercent
      當您想要更改混合垃圾回收決定時。
    • -XX:G1MixedGCCountTarget 和 -XX:G1OldCSetRegionThresholdPercent
      當您想要調整舊區域的 CSet 時。

有關溢出和用盡的日誌消息

當您在日誌中看到目標空間溢出/用盡的消息時,意味着 G1 GC 沒有足夠的內存,供存活者和/或晉升對象使用。Java 堆不能擴展,由於已達到最大值。示例消息:jvm

924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]



924.897:[GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]微服務

要緩解此問題,請嘗試如下調整:性能

增長 -XX:G1ReservePercent 選項的值(並相應增長總的堆大小),爲「目標空間」增長預留內存量。

經過減小 -XX:InitiatingHeapOccupancyPercent 提早啓動標記週期。

您也能夠經過增長 -XX:ConcGCThreads 選項的值來增長並行標記線程的數目。

巨型對象和巨型分配

對於 G1 GC,任何超過區域一半大小的對象都被視爲「巨型對象」。此類對象直接被分配到老年代中的「巨型區域」。這些巨型區域是一個連續的區域集。StartsHumongous 標記該連續集的開始,ContinuesHumongous 標記它的延續。

在分配任何巨型區域以前,會檢查標記閾值,若有必要,還會啓動一個併發週期。

在清理階段或完整的垃圾回收週期內,標記週期結束時會清理死亡的巨型對象。

爲了減小複製開銷,巨型對象未包括在疏散暫停中。完整的垃圾回收週期會對巨型對象進行壓縮。

因爲每一個 StartsHumongous 和 ContinuesHumongous 區域集只包含一個巨型對象,因此沒有使用巨型對象的終點與上個區域的終點之間的空間(即巨型對象所跨的空間)。若是對象只是略大於堆區域大小的倍數,則此類未使用的空間可能會致使堆碎片化。

若是巨型分配致使連續的併發週期,而且此類分配致使老年代碎片化,請增長 -XX:G1HeapRegionSize,這樣一來,以前的巨型對象就再也不是巨型對象了,而是採用常規的分配路徑。

總結

G1 GC 是區域化、並行-併發、增量式垃圾回收器,相比其餘 HotSpot 垃圾回收器,可提供更多可預測的暫停。增量的特性使 G1 GC 適用於更大的堆,在最壞的狀況下仍能提供不錯的響應。G1 GC 的自適應特性使 JVM 命令行只須要軟實時暫停時間目標的最大值以及 Java 堆大小的最大值和最小值,便可開始工做。

-Xmx4096m //最大內存分配
 -Xms4096m //最小內存分配
 -Xss256k //每一個線程的堆棧大小
 //-XX:NewRatio=2 年輕代和老年代大小的比例,默認是2 G1垃圾回收最好不要設置採用下面的配置
 -XX:G1NewSizePercent=30 //新生代最小值,默認值5%
 -XX:G1MaxNewSizePercent=45 //新生代最大值,默認值60%
 -XX:MetaspaceSize=256m //jdk8 元空間大小(至關於之前的perm)
 -XX:MaxMetaspaceSize=512m //jdk8最大元空間大小
 -XX:+UseG1GC //指定G1垃圾收集器
 -XX:G1HeapRegionSize=16m //G1垃圾收集器分區大小
 -XX:G1ReservePercent=25 //預留多少內存,防止晉升失敗的狀況,默認值是10
 -XX:MaxTenuringThreshold=15 //晉升的閾值,默認是15(一個存活對象經歷多少次GC週期以後晉升到老年代)
 -XX:SurvivorRatio=8 //	eden和survivor區域空間大小的比例,默認是8
 -XX:+ParallelRefProcEnabled //採用多線程的方式發現須要處理的finalize方法的對象,非多線程執行對象的finalize方法
 -XX:-OmitStackTraceInFastThrow //一些頻繁拋出的異常,JVM爲了性能優化而拋出沒有堆棧的異常,默認開啓,
 -XX:+AlwaysPreTouch //jvm預先訪問全部分配給它的內存,讓操做系統把內存真正的分配給JVM
 -XX:+PrintTenuringDistribution //顯示出survivor區間有效對象的年齡(經歷過幾回新生代回收)分佈狀況,能夠經過該參數的輸出肯定出survivor大小以及 MaxTenuringThreshold 的值
 -XX:+PrintGCApplicationStoppedTime //打印垃圾收集期間應用被暫停的時間
 -XX:+UnlockExperimentalVMOptions //打印出實驗性的參數
 -XX:InitiatingHeapOccupancyPercent=40 //內存佔用達到整個堆百分之多少的時候開啓一個GC週期,G1 GC會根據整個堆的佔用,而不是某個代的佔用狀況去觸發一個併發GC週期,0表示一直在GC,默認值是45
 -XX:MaxGCPauseMillis=20 //G1收集器GC最大停頓時間ms
 -XX:ParallelGCThreads=4 //GC在並行處理階段啓動多少個線程,默認值和平臺有關。通常不設採用默認配置
 -XX:ConcGCThreads=n //併發收集的時候使用多少個線程,默認值和平臺有關。通常不設採用默認配置
 -verbose:gc // 表示輸出虛擬機中GC的詳細狀況
 -XX:+PrintGCDetails //打印gc日誌,打印的出日誌包含日誌收集緣由,各區域變化狀況,以及用時
 -XX:+PrintHeapAtGC //打印gc先後堆詳細信息,不論是minor gc仍是full gc都會打印
 -XX:+PrintGCDateStamps //日誌中輸出時間戳
 -XX:+PrintPromotionFailure //是多大的新生代對象晉升到老生代失敗從而引起Full GC
 -XX:+HeapDumpOnOutOfMemoryError //在Out Of Memory,JVM快死掉的時候,輸出Heap Dump到指定文件。否則開發不少時候還真不知道怎麼重現錯誤
 -XX:+PrintAdaptiveSizePolicy //能夠打印出survivor的一些詳細信息,關於survivor區間是否溢出,是否有對象轉移到老年代
 -XX:+UseGCLogFileRotation //
 -XX:NumberOfGCLogFiles=5 //
 -XX:GCLogFileSize=30M //這三個參數用於設置gc文件滾動和設置滾動日誌文件的個數,爲了防止單個gc日誌文件太大,生產上建議加上這兩個參數;
 -Xloggc:/opt/logs/jetty/gc_%p.log //gc log輸出地址
 -XX:HeapDumpPath=/opt/logs/jetty/java.hprof //heap dump日誌地址
 -XX:ErrorFile=/opt/logs/jetty/hs_err_pid%p.log //JVM crash時生成crash文件的路徑
相關文章
相關標籤/搜索