問題:JVM 內存頻繁預警,內存規律性波動。
一. 查看JVM 的GC Collector:Young GC:PS Scavenge | Full GC:PS MarkSweep
PS Scavenge 新生代的收集器,也叫 Parallel Scavenge。
PS MarkSweep 老生代的收集器,也叫 Serial Old。
二. 內存曲線分析
1. 頻繁 Young GC,產生大量碎片
2. 大對象直接進入老生代
三. 嘗試優化
1. 調整內存
調大 JVM 之後(1G > 4G),曲線趨勢並沒有變化,更糟糕的是,內存越大,Full GC 掃描時間越長,時間越長, Stop the world 的時間越長,造成吞吐量損失越大。
2. 調整 JVM
(1) 調試 JVM:-Xms -Xmx -Xmn
(2) 調試 JVM Collector:-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
(2.1) 年輕代
-XX:+UseParNewGC
ParNew 基本上和 Parallel Scavenge 非常相似,唯一的區別,在於它做了強化能夠和 CMS 一起使用。
(2.2) 老生代
-XX:+UseConcMarkSweepGC
相當於"ParNew" + "CMS" + "Serial Old",即在 young generation 中採用 ParNew,多線程處理;在 tenured generation 中使用CMS,以求得到最低的暫停時間,但是,採用 CMS 有可能出現"Concurrent Mode Failure",如果出現了,就只能採用"SerialOld"模式了。
通過上述2種方法的調試,沒有從根本上解決大對象的產生,依然存在頻繁 full gc,即使調整 collector,JVM 的響應時間上去了,但吞吐量降低了。
3. 使用弱引用
雖然使用了弱引用,但是並沒有改變大數據對象直接進入堆的情況。
—————————— 本文同步發佈於 ZHANGSR 我的個人博客 ——————————