IDEA jvm 啟動調優 參考 深入理解Java虛擬機

最近看了《深入理解Java虛擬機》感觸很深,就試著對自己的idea進行調優實踐,記錄如下:
(第一次在網上發文章,如有不對指出,希望大神指正)

第一步

查看gc日志

添加配置如下:

    # 打印gc

?    -XX:+PrintGC

?    # 打印gc詳情

?    -XX:+PrintGCDetails

?    # 打印gc停頓耗時

?    -XX:+PrintGCTimeStamps

?    # 打印gc的時候添加時間標志

?    -XX:+PrintGCDateStamps

?    # 輸出位置

?    -Xloggc:/Users/Danny/Documents/java/log/idea/gc.log

日志輸出如下:

    2019-03-20T18:34:47.664-0800: 0.335: [GC (Allocation Failure) 2019-03-20T18:34:47.664-0800: 0.335: [ParNew: 34944K->4352K(39296K), 0.0235984 secs] 34944K->9107K(126720K), 0.0237457 secs] [Times: user=0.08 sys=0.02, real=0.02 secs] 

?    2019-03-20T18:34:47.777-0800: 0.448: [GC (Allocation Failure) 2019-03-20T18:34:47.777-0800: 0.448: [ParNew: 39296K->4352K(39296K), 0.0087480 secs] 44051K->12278K(126720K), 0.0088293 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 

?    2019-03-20T18:34:48.059-0800: 0.729: [GC (Allocation Failure) 2019-03-20T18:34:48.059-0800: 0.730: [ParNew: 39296K->4352K(39296K), 0.0101041 secs] 47222K->16725K(126720K), 0.0102179 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 

?    2019-03-20T18:34:48.692-0800: 1.363: [GC (Allocation Failure) 2019-03-20T18:34:48.692-0800: 1.363: [ParNew: 39296K->4352K(39296K), 0.0200235 secs] 51669K->26196K(126720K), 0.0201311 secs] [Times: user=0.06 sys=0.01, real=0.02 secs] 

?    2019-03-20T18:34:50.712-0800: 3.383: [GC (CMS Initial Mark) [1 CMS-initial-mark: 21844K(87424K)] 47248K(126720K), 0.0024990 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 

?    2019-03-20T18:34:50.715-0800: 3.386: [CMS-concurrent-mark-start]

?    2019-03-20T18:34:50.725-0800: 3.396: [CMS-concurrent-mark: 0.010/0.010 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 

?    2019-03-20T18:34:50.725-0800: 3.396: [CMS-concurrent-preclean-start]

?    2019-03-20T18:34:50.726-0800: 3.397: [CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

?    2019-03-20T18:34:50.726-0800: 3.397: [CMS-concurrent-abortable-preclean-start]

?    2019-03-20T18:34:51.149-0800: 3.820: [GC (Allocation Failure) 2019-03-20T18:34:51.149-0800: 3.820: [ParNew: 39296K->4352K(39296K), 0.0135339 secs] 61140K->35671K(126720K), 0.0136103 secs] [Times: user=0.06 sys=0.01, real=0.02 secs] 

?    2019-03-20T18:34:51.404-0800: 4.075: [GC (Allocation Failure) 2019-03-20T18:34:51.404-0800: 4.075: [ParNew: 39296K->4351K(39296K), 0.0064494 secs] 70615K->39107K(126720K), 0.0065322 secs] [Times: user=0.04 sys=0.00, real=0.01 secs] 

?    2019-03-20T18:34:51.411-0800: 4.082: [CMS-concurrent-abortable-preclean: 0.183/0.685 secs] [Times: user=2.43 sys=0.09, real=0.69 secs] 

?    2019-03-20T18:34:51.411-0800: 4.082: [GC (CMS Final Remark) [YG occupancy: 4956 K (39296 K)]2019-03-20T18:34:51.411-0800: 4.082: [Rescan (parallel) , 0.0023462 secs]2019-03-20T18:34:51.414-0800: 4.085: [weak refs processing, 0.0000408 secs]2019-03-20T18:34:51.414-0800: 4.085: [class unloading, 0.0033510 secs]2019-03-20T18:34:51.417-0800: 4.088: [scrub symbol table, 0.0027581 secs]2019-03-20T18:34:51.420-0800: 4.091: [scrub string table, 0.0003787 secs][1 CMS-remark: 34755K(87424K)] 39712K(126720K), 0.0094268 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 

?    2019-03-20T18:34:51.421-0800: 4.092: [CMS-concurrent-sweep-start]

?    2019-03-20T18:34:51.433-0800: 4.104: [CMS-concurrent-sweep: 0.012/0.012 secs] [Times: user=0.07 sys=0.00, real=0.01 secs] 

?    2019-03-20T18:34:51.433-0800: 4.104: [CMS-concurrent-reset-start]

?    2019-03-20T18:34:51.438-0800: 4.109: [CMS-concurrent-reset: 0.006/0.006 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 

?    2019-03-20T18:34:51.515-0800: 4.185: [GC (Allocation Failure) 2019-03-20T18:34:51.515-0800: 4.186: [ParNew: 39295K->4029K(39296K), 0.0026156 secs] 69328K->34062K(126720K), 0.0026858 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 

關于cms的幾個階段可以參考如下

[http://fengfu.io/2016/06/21/JVM-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E5%99%A8CMS%E4%B9%8B%E5%90%84%E9%98%B6%E6%AE%B5%E6%95%B4%E7%90%86/]

[https://www.cnblogs.com/zhangxiaoguang/p/5792468.html]

? log里頭99%都是GC (Allocation Failure)造成的young gc。Allocation Failure表示向young generation(eden)給新對象申請空間,但是young generation(eden)剩余的合適空間不夠所需的大小導致的minor gc。

最后看full gc 的擴容

    2019-03-20T20:36:00.277-0800: 3632.918: [Full GC (System.gc()) 

?    2019-03-20T20:36:00.278-0800: 3632.918: [CMS: 184874K->98447K(289064K), 1.3009498 secs] 200372K->98447K(328360K), [Metaspace: 240354K->240354K(1271808K)], 1.3052543 secs] [Times: user=0.90 sys=0.40, real=1.31 secs] 

?    2019-03-20T20:43:18.915-0800: 4071.564: [GC (Allocation Failure) 2019-03-20T20:43:18.915-0800: 4071.564: [ParNew: 115712K->1768K(130176K), 0.0092860 secs] 214159K->100216K(419240K), 0.0096646 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 

?    2019-03-20T20:50:39.596-0800: 4512.254: [GC (Allocation Failure) 

?    2019-03-20T20:50:39.681-0800: 4512.339: [ParNew: 117480K->1873K(130176K), 0.0098727 secs] 215928K->100321K(419240K), 0.0955434 secs] [Times: user=0.05 sys=0.01, real=0.10 secs] 

圖如下:


Screen Shot 2019-03-22 at 01.41.32.png
Pasted Graphic 3.png

最終確定配置如下

?

    # eden 113m + from 14.125m + to 14.125m(上圖程序自動擴容顯示)

?    -Xmn156m

?    # new 150m + old 282.289m

?    -Xms468m

?    -Xmx768m

?    # 283.953 Metaspace擴容時觸發FullGC的初始化閾值(默認值FGC的閾值是約20.8m)

?    -XX:MetaspaceSize=300m

?    # Metaspace最大值

?    -XX:MaxMetaspaceSize=300m

調優后效果如下:

Screen Shot 2019-03-21 at 14.03.20.png

? 還是發生了兩次old的gc,按常理內存是夠的所以在此查看日志:

16.577: [GC (Allocation Failure) 16.577: [ParNew Desired survivor size 8159232 bytes, new threshold 1 (max 6) - age   1:   11982624 bytes,   11982624 total

: 142742K->15936K(143808K), 0.0211620 secs] 296485K->180210K(463296K), 0.0212467 secs] [Times: user=0.12 sys=0.01, real=0.02 secs] 

16.599: [GC (CMS Initial Mark) [1 CMS-initial-mark: 164274K(319488K)] 180483K(463296K), 0.0188112 secs] [Times: user=0.04 sys=0.00, real=0.02 secs] 

16.618: [CMS-concurrent-mark-start]

16.753: [CMS-concurrent-mark: 0.125/0.135 secs] [Times: user=0.67 sys=0.02, real=0.14 secs] 

16.753: [CMS-concurrent-preclean-start]

16.759: [CMS-concurrent-preclean: 0.005/0.006 secs] [Times: user=0.04 sys=0.00, real=0.00 secs] 

16.759: [CMS-concurrent-abortable-preclean-start]

17.095: [CMS-concurrent-abortable-preclean: 0.324/0.336 secs] [Times: user=1.99 sys=0.08, real=0.34 secs] 

17.096: [GC (CMS Final Remark) [YG occupancy: 83210 K (143808 K)]17.096: [Rescan (parallel) , 0.0317955 secs]17.127: [weak refs processing, 0.0002594 secs][1 CMS-remark: 164274K(319488K)] 247484K(463296K), 0.0321534 secs] [Times: user=0.20 sys=0.01, real=0.03 secs] 

17.128: [CMS-concurrent-sweep-start]

17.312: [CMS-concurrent-sweep: 0.165/0.184 secs] [Times: user=1.11 sys=0.05, real=0.19 secs] 

17.312: [CMS-concurrent-reset-start]

17.338: [CMS-concurrent-reset: 0.023/0.026 secs] [Times: user=0.12 sys=0.01, real=0.02 secs] 

? 經過分析發現在old空間還有124M不應該發生gc,通過查閱書籍《深入了解java虛擬機》發現CMS有一個浮動垃圾預留空間默認為68%,但是是一個保守估計,現在的技術已經可以提高到92%,所以跳高參數比值如下:

這里分析的有誤,后查資料發現java8這個值的默認值為92%,Java8之前的為68%,那為什么還會有FGC呢,這是因為默認值只是第一次使用有效,之后虛擬機會動態調整的,所以這里可以調小點,然后加上XX:+UseCMSInitiatingOccupancyOnly 使其不會改變。

# new 150m + old 282.289m/0.85 = 330 (因為處理浮動垃圾需要預留空間CMSInitiatingOccupancyFraction=85)

-Xms480m

-Xmx480m

# eden 113m + from 14.125m + to 14.125m(上圖程序自動擴容顯示) 只能使用90%

-Xmn150m

# 如果沒有 -XX:+UseCMSInitiatingOccupancyOnly 這個參數, 只有第一次會使用85這個值. 后面的情況會自動調整。 注意這里,java8之前默認值為68%,java8的時候變成了92%

-XX:CMSInitiatingOccupancyFraction=85

-XX:+UseCMSInitiatingOccupancyOnly


效果如下圖:

Pasted Graphic 5.png

果然如我所料,FGC一次也沒有了,真的是好興奮。

? 最后在適當加大new的內存,因為觀察gc日志發現每次的回收大小大概20M左右,但是survivor的大小只有15M,所以在此調整所有的空間如下:

# new 150m + old 282.289m/0.85 = 330 (因為處理浮動垃圾需要預留空間CMSInitiatingOccupancyFraction=85)

-Xms500m

-Xmx500m

# eden 113m + from 14.125m + to 14.125m(上圖程序自動擴容顯示) 只能使用90%

-Xmn200m

# 如果沒有 -XX:+UseCMSInitiatingOccupancyOnly 這個參數, 只有第一次會使用85這個值. 后面的情況會自動調整。

-XX:CMSInitiatingOccupancyFraction=85

-XX:+UseCMSInitiatingOccupancyOnly

Pasted Graphic 7.png

? 效果完美,而且使用的內存最小化的方案,哈哈,可能我平時也是比較摳門吧,對于節省方面達到了斤斤計較的地步了。但是做技術應該有精益求精的精神,在對于微服務方面,上千上萬的服務中,每個節省一些空間,最后都是巨大效益。而且空間大不僅浪費空間,而且還會浪費gc的時間。

最終配置如下:

# 設置為服務器模式 使用C2深度編譯,雖然編譯耗時長,但是后期運行深度優化的代碼速度快

# 但是對于一直不關idea的情況,推薦使用

-server

# new 150m + old 282.289m/0.85 = 330 (因為處理浮動垃圾需要預留空間CMSInitiatingOccupancyFraction=85)

-Xms500m

-Xmx500m

# eden 113m + from 14.125m + to 14.125m(上圖程序自動擴容顯示) 只能使用90%

-Xmn200m

-Xss256k

# 283.953 Metaspace擴容時觸發FullGC的初始化閾值(默認值FGC的閾值是約20.8m)

-XX:MetaspaceSize=300m

# Metaspace最大值

-XX:MaxMetaspaceSize=300m

# 關閉System.gc() 

-XX:+DisableExplicitGC

-XX:+UseConcMarkSweepGC

# 設置cms在老年代空間被使用多少百分比之后觸發垃圾回收默認68(因為有浮動垃圾)

-XX:CMSInitiatingOccupancyFraction=85

# 如果沒有 -XX:+UseCMSInitiatingOccupancyOnly 這個參數, 只有第一次會使用85這個值. 后面的情況會自動調整。

-XX:+UseCMSInitiatingOccupancyOnly

# 節省64位指針占用的空間,代價是JVM額外開銷 由ergonomics控制 

-XX:+UseCompressedOops

# 增大軟引用在JVM中的存活時長(堆空閑空間越大越久)

-XX:SoftRefLRUPolicyMSPerMB=50

-Dfile.encoding=UTF-8

-ea

-Dsun.io.useCanonCaches=false

-Djava.net.preferIPv4Stack=true

-Djdk.http.auth.tunneling.disabledSchemes=""

-XX:+HeapDumpOnOutOfMemoryError

# 禁止字節碼校驗

-Xverify:none

# 省略異常棧信息從而快速拋出,JVM對一些特定的異常類型做了FastThrow優化,如果檢測到在代碼里某個位置連續

# 多次拋出同一類型異常的話,C2會決定用FastThrow方式來拋出異常,而異常Trace即詳細的異常棧信息會被清空。

# 這種異常拋出速度非常快,因為不需要在堆里分配內存,也不需要構造完整的異常棧信息。

-XX:-OmitStackTraceInFastThrow



-XX:ErrorFile=$USER_HOME/java_error_in_idea_%p.log

-XX:HeapDumpPath=$USER_HOME/java_error_in_idea.hprof



# 打印gc

-XX:+PrintGC

# 打印gc詳情

-XX:+PrintGCDetails

# 打印gc停頓耗時

-XX:+PrintGCTimeStamps

# 輸出位置

-Xloggc:/Users/Danny/Documents/java/log/idea/gc.log



# 打印每次的年齡閥值

# -XX:+PrintTenuringDistribution

# 啰嗦的gc信息 上面已經包含了這個參數

# -verbose:gc

# 打印gc的時候添加時間標志

# -XX:+PrintGCDateStamps

# 代碼緩存,用于存放Just In Time編譯后的本地代碼,如果塞滿,JVM將只解釋執行,不再編譯native代碼,server 64位的默認值

# -XX:ReservedCodeCacheSize=240m

# 當頻繁執行某個方法時,生成字節碼來加快反射的執行速度,查看jvm優化陷阱

# 些多態方法調用點的性能反而會顯著下降。所以,為了適應多層編譯模式,JDK 7里這兩個參數的默認值就被改為false了

# -XX:+UseFastAccessorMethods

# 每次永久存儲區滿了后一般GC算法在做擴展分配內存前都會觸發一次FULL GC,除非設置了次選項 感覺沒用

# -Xnoclassgc

# 默認開

# -XX:+UseParNewGC

# 設置后發現沒有用 虛擬機會自動調節

# -XX:MaxTenuringThreshold=6

# 默認開為了減少第二次暫停的時間,開啟并行remark(第三階段的CMS Remark) 會增加gc總時間

# -XX:+CMSParallelRemarkEnabled

# 默認開當FCC 的時候啟用CMS壓縮(因為cms會產生碎片,所以要手動壓縮參數)

# -XX:+UseCMSCompactAtFullCollection
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容