JVM調優分享

面試精選集,快快前往領取吧!offer.liangsonghua.me/。關注微信公衆號:松花皮蛋的黑板報,獲取更多精彩!

一. 默認配置

配置及說明:

-Djava.library.path=/usr/local/lib-server -Xms6144m-Xmx6144m-XX:MaxPermSize=256m-Dsun.net.client.defaultConnectTimeout=60000-Dsun.net.client.defaultReadTimeout=60000-Dnetworkaddress.cache.ttl=300-Dsun.net.inetaddr.ttl=300

-Djava.library.path

指定非java類包的位置(如:dll,so)。

-server

如果tomcat是運行在生產環境中的,這個參數必須加上,-server參數可以使tomcat以server模式運行,這個模式下將擁有:更大、更高的併發處理能力,更快更強捷的JVM垃圾回收機制,可以有更大的負載與吞吐量。

-Xms<size>和-Xmx<size>

前者表示JVM初始化堆的大小,後者表示JVM堆的最大值。一般把Xms與Xmx兩個值設成一樣是最優的做法,否則會導致jvm有較爲頻繁的GC,影響系統性能。

-XX:MaxPermSize=256m

初始化JVM非堆(持久代、永久代、方法區)最大值。

-Dsun.net.client.defaultConnectTimeout=60000

連接建立超時設置。

-Dsun.net.client.defaultReadTimeout=60000

內容獲取超時設置。

-Dnetworkaddress.cache.ttl=300

jvm dns緩存超時的相關設置。

-Dsun.net.inetaddr.ttl=300

jvm dns緩存超時的相關設置。

二. 調整GC策略

背景:

線上頻繁發生報警(堆內存佔用超過80%),創建dump文件並分析發現,大量數據爲char[]、String等類型,主要爲業務模塊產生的臨時數據,以mybatis查詢緩存字符串爲主,無大對象,過段時間full gc會自行回收(但回收量有時較大,有時較少)。考慮調整GC策略。

配置及說明:

-XX:+UseParNewGC-XX:+UseConcMarkSweepGC-XX:+CMSParallelRemarkEnabled

-XX:+UseParNewGC

設置年輕代爲並行收集。可與CMS收集同時使用。JDK5.0以上,JVM會根據系統配置自行設置,所以無需再設置此值。

-XX:+UseConcMarkSweepGC

設置年老代爲CMS併發收集。CMS流程:初始標記(CMS-initial-mark) -> 併發標記(CMS-concurrent-mark) -> 重新標記(CMS-remark) -> 併發清除(CMS-concurrent-sweep) ->併發重設狀態等待下次CMS的觸發(CMS-concurrent-reset)。

-XX:+CMSParallelRemarkEnabled

CMS開啓並行remark。

-XX:+CMSScavengeBeforeRemark

強制remark之前開始一次minor gc,減少remark的暫停時間。

-Xss

設置每個線程的堆棧大小。JDK5.0以後每個線程堆 棧大小爲1M,以前每個線程堆棧大小爲256K。根據應用的線程所需內存大小進行調整。在相同物理內存下,減小這個值能生成更多的線程。但是操作系統對一 個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。線程棧的大小是個雙刃劍,如果設置過小,可能會出現棧溢出,特別是在該線程內有遞歸、大的循環時出現溢出的可能性更大,如果該值設置過大,就有影響到創建棧的數量,如果是多線程的應用,就會出現內存溢出的錯誤。線出現過棧溢出。

三. 保底配置

背景:

線上頻繁發生報警(堆內存佔用超過80%),調大堆內存到6144m、調整GC策略後依然存在問題,分析dump文件發現主要數據爲char[]、String等類型的臨時數據,暫增加保底策略,堆內存達到70%後強制CMS GC。

配置及說明

-XX:CMSInitiatingOccupancyFraction=70-XX:+UseCMSInitiatingOccupancyOnly

XX:CMSInitiatingOccupancyFraction=70

堆內存使用達到70%後強制開始CMS收集。

-XX:+UseCMSInitiatingOccupancyOnly

只是用設定的回收閾值(上面指定的70%),如果不指定,JVM僅在第一次使用設定值,後續則自動調整。

四. 記錄GC日誌

背景:增加gc日誌方便後續的JVM優化分析和問題排查。

配置及說明:

-XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:/export/Logs/gc.log-XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=10-XX:GCLogFileSize=1m

-XX:+PrintGCDetails

輸出GC的詳細日誌。

-XX:+PrintGCDateStamps

輸出GC的時間戳(以日期的形式)。

-Xloggc:/export/Logs/gc.log

gc日誌文件的輸出路徑。

-XX:+UseGCLogFileRotation

打開或關閉GC日誌滾動記錄功能,要求必須設置 -Xloggc參數。

-XX:NumberOfGCLogFiles=3

設置滾動日誌文件的個數,必須大於1。

-XX:GCLogFileSize=512k

設置滾動日誌文件的大小,必須大於8k。

-XX:+PrintHeapAtGC

在進行GC的前後打印出堆的信息,該日誌輸出量較大,可以不開啓。

五. 進一步優化

背景:

增加70%強制CMS GC配置後不再觸發報警,但依然會在某特殊場景頻繁full gc。通過gc分析,懷疑在這種特殊場景下:內存分配過快導致很多數據在年輕代待的時間太短就進入老年代,致使老年代中不斷堆積稍後就無效的對象,最終觸發full gc。考慮增大年輕代內存、eden與survivor分配策略。

系統分析:

主要的內存消耗是業務產生的臨時性數據,這些數據業務結束後即無效,增大年輕代有助於讓這些臨時性數據減少進入老年代進而觸發full gc的概率,但是也不能一味增加年輕代,年輕代過大會影響minor gc過慢,系統吞吐量降低。

配置及說明:

-XX:NewRatio=3-XX:SurvivorRatio=4

-XX:NewRatio=3

設置老年代與新生代的比例。指定老年代OC:新生代YC爲 3:1。老年代佔堆大小的 3/4,新生代佔 1/4。

-XX:SurvivorRatio=4

年輕代中Eden區與Survivor區的大小比值。設置爲4,則表示S0C:S1C:EC=1:1:4。該配置默認爲8。增大Survivor區可以容納更多的存活對象。這樣就會防止因爲Survivor區太小導致很對存活對象還沒有達到MaxTenuringThreshold閾值就直接進入老年代,潛在增大old gc的觸發頻率。

-XX:ParallelGCThreads=8

設置並行垃圾收集的線程數量。8表示每次並行垃圾收集將有8個線程執行。如果不明確設置該標誌,虛擬機將使用基於可用 (虛擬) 處理器數量計算的默認值。決定因素是由 Java Runtime。availableProcessors() 方法的返回值 N,如果 N<=8,並行垃圾收集器數=N;如果 N>8,JVM會調整算法,每超出5/8個CPU啓動一個新的線程,並行垃圾收集器數= 8 + ((N – 8) * 5/8) = 3+5*N/8。如16覈對應13線程,32覈對應23線程。當 JVM 獨佔地使用系統和處理器時使用默認設置更有意義。但是,如果有多個 JVM(或其他耗 CPU 的系統) 在同一臺機器上運行,我們應該使用 – XX:ParallelGCThreads 來減少垃圾收集線程數到一個適當的值。例如,如果 4 個以服務器方式運行的 JVM 同時跑在在一個具有 16 核處理器的機器上,設置 – XX:ParallelGCThreads=4 是明智的,它能使不同 JVM 的垃圾收集器不會相互干擾。

文章來源:www.liangsonghua.me

作者介紹:京東資深工程師-樑鬆華,在穩定性保障、敏捷開發、JAVA高級、微服務架構方面有深入的理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章