Tomcat出現Unloading class sun.reflect.GeneratedMethodAccessor216]解決方案
在配置catalina.sh中加入-XX:CMSFullGCsBeforeCompaction=1
如:
export JAVA_HOME=/xx/local/jdk/jdk1.6.0_43
export CLASSPATH=.:$JAVA_HOME/lib.tools.jar
export JAVA_HOME CLASSPATH PATH
export JAVA_OPTS="-Xmx1G -Xms1G -Xmn1G -XX:MaxPermSize=1024m -XX:+UseConcMarkSweepGC -Xloggc:/xx/log_gc.log -XX:+UseCMSCompactAtFullCollection -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled -XX:ParallelGCThreads=4 -XX:+UseAdaptiveSizePolicy -server -XX:HeapDumpPath=/xx/temp/ -XX:+UseFastAccessorMethods -XX:-UseBoundThreads -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9093 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false --XX:CMSFullGCsBeforeCompaction=1"
98%的Java物件,在建立之後不久就變成了非活動物件;只有2%的物件,會在長時間一直處於活動狀態。major gc需要的時間比minor gc長的多,所以我們要減少major gc次數,提高minor gc的效率,儘量將非活動物件消滅在年輕代。
針對上述分析報告,從JVM當前引數配置中找到了些原因,如下:
-Xms768m -Xmx1280m jvm堆的最小值和最大值設定,一般設成相同值,避免頻繁分配堆空間
-XX:NewSize=128m -XX:MaxNewSize=128m 年輕代最小值和最大值設定(年輕代設定了,年老代也就定了),也可以用引數-XX:NewRatio=4,年老代和年輕代的大小比,這裡128m有點小了,官方建議的是heap的3/8,差不多280m
-XX:PermSize=96m -XX:MaxPermSize=128m 持久代最小值和最大值設定
-XX:MaxTenuringThreshold=0 經過多少次minor gc 後進入年老代,設定為0的話直接進入年老代,這是不太合理的,正常應該在年輕代多呆一段時間,真正需要到年老代的才轉過去
-XX:SurvivorRatio=20000 年輕代中eden和一塊suvivor區的空間比例,這裡設定成20000有問題,suvivor區空間幾乎為0,一次minor gc後基本都轉到年老代了,年輕代沒有起到過濾左右
-XX:+UseParNewGC 年輕代採用並行gc策略,JDK5.0以上,JVM會根據系統配置自行設定,所以無需再設定此值。使用多執行緒收集,提高吞吐量(-XX:ParallelGCThreads
-XX:+UseConcMarkSweepGC 年老代採用併發gc策略,和應用程式併發執行,減少pause time,但是需要更大的堆區,因為併發執行,有碎片(-XX:+UseParallelOldGC 年老代垃圾收集方式為並行收集,這個是Java 6出現的引數選項)
-XX:+CMSPermGenSweepingEnabled 為了避免Perm區滿引起的full gc,建議開啟CMS回收Perm區選項
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 列印gc日誌
-XX:CMSInitiatingOccupancyFraction=1 年老代使用空間比達到這個值時開始cms gc,預設是在年老代佔滿68%的時候開始進行CMS收集,這裡設定成1是不合理的,會導致CMS GC頻繁發生,從gc日誌裡可以看出來,CMS GC和minor GC幾乎一樣多
-XX:+CMSIncrementalMode 啟動i-CMS模式,增量模式,將cms gc過程分成6個階段,其中階段initial Mark和remark時需要pause,這6個階段在兩次minor gc的間隔期執行,具體執行起止時間由下面兩個引數決定。拆分成小階段增量執行時,可以避免應用被中斷時間過長,極端情況是如果只有一個cpu,那麼得等全部做完這6個階段才能釋放cpu,如果是多cpu這個模式開啟與否應該影響不大。
-XX:CMSIncrementalDutyCycleMin=10 預設值10 啟動CMS的下線
-XX:CMSIncrementalDutyCycle=30 預設值50 啟動CMS的上線
-XX:+UseCMSCompactAtFullCollection 在FULL GC的時候, 對年老代的壓縮。CMS是不會移動記憶體的, 因此這個非常容易產生碎片, 導致記憶體不夠用, 因此, 記憶體的壓縮這個時候就會被啟用。 可能會影響效能,但是可以消除碎片,增加這個引數是個好習慣。
-XX:CMSFullGCsBeforeCompaction=0 上面配置開啟的情況下,這裡設定多少次Full GC後,對年老代進行壓縮,這裡設定成0不知道什麼意思,可以根據線上full gc 的頻率確定,頻率高,這個值可以大點,比如5,反之頻率低,這個值可以小點,比如1
-XX:CMSMarkStackSize=8M
-XX:CMSMarkStackSizeMax=32M