JAVA系列之JVM內存調優( 二 )


2.1 吞吐量優先的并行收集器java -server -Xmx4g -Xms4g -Xmn2g –Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy

-XX:+UseParallelGC:選擇垃圾收集器為并行收集器 。此配置僅對年輕代有效 。即上述配置下 , 年輕代使用并發收集,而年老代仍舊使用串行收集 。-XX:ParallelGCThreads=20:配置并行收集器的線程數,即:同時多少個線程一起進行垃圾回收 。此值最好配置與處理器數目相等 。-XX:+UseParallelOldGC:配置年老代垃圾收集方式為并行收集 。JDK6.0支持對年老代并行收集 。-XX:+UseAdaptiveSizePolicy:設置此選項后,并行收集器會自動選擇年輕代區大小和相應的Survivor區比例 , 以達到目標系統規定的最低相應時間或者收集頻率等,此值建議使用并行收集器時,一直打開 。
2.2 響應時間優先的并發收集器java -server -Xmx4g -Xms4g -Xmn2g –Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
-XX:+UseConcMarkSweepGC: 設置年老代為并發收集-XX:+UseParNewGC: 設置年輕代為并行收集 。可與CMS收集同時使用-XX:CMSFullGCsBeforeCompaction:由于并發收集器不對內存空間進行壓縮、整理,所以運行一段時間以后會產生“碎片”,使得運行效率降低 。此值設置運行多少次GC以后對內存空間進行壓縮、整理 。-XX:+UseCMSCompactAtFullCollection:打開對年老代的壓縮 ??赡軙绊懶阅?,但是可以消除碎片
3、其他輔助配置GC日志打印
-XX:+PrintGC:輸出形式:[GC 118250K->113543K(130112K), 0.0094143 secs] [Full GC 121376K->10414K(130112K), 0.0650971 secs]-XX:+PrintGCDetails:輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]
OOM生成dump文件
-XX:+HeapDumpOnOutOfMemoryError 表示jvm發生oom異常時,自動生成dump文件-XX:HeapDumpPath= 表示生成dump文件的存放目錄
四、內存溢出排查【JAVA系列之JVM內存調優】一般來說內存溢出主要分為以下幾類:
堆溢出(java.lang.OutOfMemoryError: Java heap space)棧深度不夠( java.lang.StackOverflowError)棧線程數不夠(java.lang.OutOfMemoryError: unable to create new native thread)元空間溢出(java.lang.OutOfMemoryError: Metaspace)
JAVA系列之JVM內存調優

文章插圖
1、元空間溢出(java.lang.OutOfMemoryError: Metaspace)Metaspace元空間主要是存儲類的元數據信息,各種類描述信息,比如類名、屬性、方法、訪問限制等,按照一定的結構存儲在Metaspace里 。一般來說,元空間大小是固定不變的 。在出現溢出后,首先通過命令或監控工具(如下圖)查看元空間大小,再檢查是否-XX:MaxMetaspaceSize配置太小導致 。
JAVA系列之JVM內存調優

文章插圖
JAVA系列之JVM內存調優

文章插圖
如果發現元空間大小是持續上漲的 , 則需要檢查代碼是否存在大量的反射類加載、動態代理生成的類加載等導致 ??梢酝ㄟ^-XX:+TraceClassLoading -XX:+TraceClassUnloading記錄下類的加載和卸載情況,反推具體問題代碼 。
JAVA系列之JVM內存調優

文章插圖
2、棧深度不夠(java.lang.StackOverflowError)引發StackOverFlowError的常見原因有:
  • 無限循環遞歸調用
  • 同一時間執行大量方法,資源耗盡
  • 方法中聲明大量局部變量
  • 其它消耗棧資源的方法
  • xss配置太小導致
/** * VM Args: -Xss128k */public class JavaStackSOF {private int stackLength = 1;public void stackLeak() {stackLength++;stackLeak();}public static void main(String[] args) {JavaStackSOF oom = new JavaStackSOF();try{oom.stackLeak();}catch(Throwable e) {System.out.println("stack length:" + oom.stackLength);throw e;}}}stack length:2101Exception in thread "main" java.lang.StackOverflowErrorat com.sandy.jvm.chapter02.JavaStackSOF.stackLeak(JavaStackSOF.java:13)at com.sandy.jvm.chapter02.JavaStackSOF.stackLeak(JavaStackSOF.java:14)at com.sandy.jvm.chapter02.JavaStackSOF.stackLeak(JavaStackSOF.java:14)3、棧線程數不夠(java.lang.OutOfMemoryError: unable to create new native thread)這類錯誤目前在生成系統只遇到過一次 , 原因是:linux系統中非root用戶默認創建線程數最多是1024 。解決辦法是修改文件:/etc/security/limits.d/90-nproc.conf還有一種情況是-xss配置太大 , 那么操作系統可創建的最大線程數太小導致,一般除非誤操作是不會出現此問題的 。

推薦閱讀