JVM內(nèi)存設(shè)置多大合適?Xmx和Xmn如何設(shè)置?

問(wèn)題:
新上線一個(gè)java服務(wù),或者是RPC或者是WEB站點(diǎn), 內(nèi)存的設(shè)置該怎么設(shè)置呢?設(shè)置成多大比較合適,既不浪費(fèi)內(nèi)存,又不影響性能呢?

分析:
依據(jù)的原則是根據(jù)Java Performance里面的推薦公式來(lái)進(jìn)行設(shè)置。

296d1509689688.png

具體來(lái)講:
Java整個(gè)堆大小設(shè)置,Xmx 和 Xms設(shè)置為老年代存活對(duì)象的3-4倍,即FullGC之后的老年代內(nèi)存占用的3-4倍
永久代 PermSize和MaxPermSize設(shè)置為老年代存活對(duì)象的1.2-1.5倍。
年輕代Xmn的設(shè)置為老年代存活對(duì)象的1-1.5倍。
老年代的內(nèi)存大小設(shè)置為老年代存活對(duì)象的2-3倍。

BTW:
1、Sun官方建議年輕代的大小為整個(gè)堆的3/8左右, 所以按照上述設(shè)置的方式,基本符合Sun的建議。
2、堆大小=年輕代大小+年老代大小, 即xmx=xmn+老年代大小 。 Permsize不影響堆大小。
3、為什么要按照上面的來(lái)進(jìn)行設(shè)置呢? 沒(méi)有具體的說(shuō)明,但應(yīng)該是根據(jù)多種調(diào)優(yōu)之后得出的一個(gè)結(jié)論。

如何確認(rèn)老年代存活對(duì)象大???
方式1(推薦/比較穩(wěn)妥):
JVM參數(shù)中添加GC日志,GC日志中會(huì)記錄每次FullGC之后各代的內(nèi)存大小,觀察老年代GC之后的空間大小。可觀察一段時(shí)間內(nèi)(比如2天)的FullGC之后的內(nèi)存情況,根據(jù)多次的FullGC之后的老年代的空間大小數(shù)據(jù)來(lái)預(yù)估FullGC之后老年代的存活對(duì)象大?。筛鶕?jù)多次FullGC之后的內(nèi)存大小取平均值)

方式2:(強(qiáng)制觸發(fā)FullGC, 會(huì)影響線上服務(wù),慎用)
方式1的方式比較可行,但需要更改JVM參數(shù),并分析日志。同時(shí),在使用CMS回收器的時(shí)候,有可能不能觸發(fā)FullGC(只發(fā)生CMS GC),所以日志中并沒(méi)有記錄FullGC的日志。在分析的時(shí)候就比較難處理。
BTW:使用jstat -gcutil工具來(lái)看FullGC的時(shí)候, CMS GC是會(huì)造成2次的FullGC次數(shù)增加。 具體可參見(jiàn)之前寫(xiě)的一篇關(guān)于jstat使用的文章
所以,有時(shí)候需要強(qiáng)制觸發(fā)一次FullGC,來(lái)觀察FullGC之后的老年代存活對(duì)象大小。
注:強(qiáng)制觸發(fā)FullGC,會(huì)造成線上服務(wù)停頓(STW),要謹(jǐn)慎,建議的操作方式為,在強(qiáng)制FullGC前先把服務(wù)節(jié)點(diǎn)摘除,F(xiàn)ullGC之后再將服務(wù)掛回可用節(jié)點(diǎn),對(duì)外提供服務(wù)
在不同時(shí)間段觸發(fā)FullGC,根據(jù)多次FullGC之后的老年代內(nèi)存情況來(lái)預(yù)估FullGC之后的老年代存活對(duì)象大小

如何觸發(fā)FullGC ?
使用jmap工具可觸發(fā)FullGC
jmap -dump:live,format=b,file=heap.bin <pid> 將當(dāng)前的存活對(duì)象dump到文件,此時(shí)會(huì)觸發(fā)FullGC
jmap -histo:live <pid> 打印每個(gè)class的實(shí)例數(shù)目,內(nèi)存占用,類(lèi)全名信息.live子參數(shù)加上后,只統(tǒng)計(jì)活的對(duì)象數(shù)量. 此時(shí)會(huì)觸發(fā)FullGC

具體操作實(shí)例:
以我司的一個(gè)RPC服務(wù)為例。
BTW:剛上線的新服務(wù),不知道該設(shè)置多大的內(nèi)存的時(shí)候,可以先多設(shè)置一點(diǎn)內(nèi)存,然后根據(jù)GC之后的情況來(lái)進(jìn)行分析。
初始JVM內(nèi)存參數(shù)設(shè)置為: Xmx=2G Xms=2G xmn=1G

使用jstat 查看當(dāng)前的GC情況。如下圖:

23b61509689687.png

YGC平均耗時(shí): 173.825s/15799=11ms
FGC平均耗時(shí):0.817s/41=19.9ms
平均大約10-20s會(huì)產(chǎn)生一次YGC

看起來(lái)似乎不錯(cuò),YGC觸發(fā)的頻率不高,F(xiàn)GC的耗時(shí)也不高,但這樣的內(nèi)存設(shè)置是不是有些浪費(fèi)呢?
為了快速看數(shù)據(jù),我們使用了方式2,產(chǎn)生了幾次FullGC,F(xiàn)ullGC之后,使用的jmap -heap 來(lái)看的當(dāng)前的堆內(nèi)存情況(也可以根據(jù)GC日志來(lái)看)
heap情況如下圖:(命令 : jmap -heap <pid>)

f9c71509689687.png

上圖中的concurrent mark-sweep generation即為老年代的內(nèi)存描述。
老年代的內(nèi)存占用為100M左右。 按照整個(gè)堆大小是老年代(FullGC)之后的3-4倍計(jì)算的話,設(shè)置各代的內(nèi)存情況如下:
Xmx=512m Xms=512m Xmn=128m PermSize=128m 老年代的大小為 (512-128=384m)為老年代存活對(duì)象大小的3倍左右
調(diào)整之后的,heap情況

aaaaa689686.png

GC情況如下:

bbbbb689686.png

YGC 差不多在10s左右觸發(fā)一次。每次YGC平均耗時(shí)大約9.41ms??山邮堋?br> FGC平均耗時(shí):0.016s/2=8ms
整體的GC耗時(shí)減少。但GC頻率比之前的2G時(shí)的要多了一些。

注: 看上述GC的時(shí)候,發(fā)現(xiàn)YGC的次數(shù)突然會(huì)增多很多個(gè),比如 從1359次到了1364次。具體原因是?

總結(jié):
在內(nèi)存相對(duì)緊張的情況下,可以按照上述的方式來(lái)進(jìn)行內(nèi)存的調(diào)優(yōu), 找到一個(gè)在GC頻率和GC耗時(shí)上都可接受的一個(gè)內(nèi)存設(shè)置,可以用較小的內(nèi)存滿足當(dāng)前的服務(wù)需要
但當(dāng)內(nèi)存相對(duì)寬裕的時(shí)候,可以相對(duì)給服務(wù)多增加一點(diǎn)內(nèi)存,可以減少GC的頻率,GC的耗時(shí)相應(yīng)會(huì)增加一些。 一般要求低延時(shí)的可以考慮多設(shè)置一點(diǎn)內(nèi)存, 對(duì)延時(shí)要求不高的,可以按照上述方式設(shè)置較小內(nèi)存。

補(bǔ)充:
永久代(方法區(qū))并不在堆內(nèi),所以之前有看過(guò)一篇文章中描述的 整個(gè)堆大小=年輕代+年老代+永久代的描述是不正確的。

轉(zhuǎn)自:

https://blog.csdn.net/losetowin/article/details/78569001

補(bǔ)充

-verbose:gc 現(xiàn)實(shí)垃圾收集信息
-Xloggc:gc.log 指定垃圾收集日志文件
-Xmn:young generation的heap大小,一般設(shè)置為Xmx的3、4分之一
-XX:SurvivorRatio=2 :生還者池的大小,默認(rèn)是2,如果垃圾回收變成了瓶頸,您可以嘗試定制生成池設(shè)置

-XX:NewSize: 新生成的池的初始大小。 缺省值為2M。
-XX:MaxNewSize: 新生成的池的最大大小。 缺省值為32M。

+XX:AggressiveHeap 會(huì)使得 Xms沒(méi)有意義。這個(gè)參數(shù)讓jvm忽略Xmx參數(shù),瘋狂地吃完一個(gè)G物理內(nèi)存,再吃盡一個(gè)G的swap。
-Xss:每個(gè)線程的Stack大小,“-Xss 15120” 這使得JBoss每增加一個(gè)線程(thread)就會(huì)立即消耗15M內(nèi)存,而最佳值應(yīng)該是128K,默認(rèn)值好像是512k.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前,它的class會(huì)被類(lèi)裝載器裝入方法區(qū)(Permanent區(qū)),執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,845評(píng)論 0 7
  • 轉(zhuǎn)載blog.csdn.net/ning109314/article/details/10411495/ JVM工...
    forever_smile閱讀 5,507評(píng)論 1 56
  • 參數(shù)設(shè)置 在Java虛擬機(jī)的參數(shù)中,有3種表示方法用“ps -ef |grep "java"命令,可以得到當(dāng)前Ja...
    九問(wèn)閱讀 9,280評(píng)論 2 52
  • 1. 前言 網(wǎng)上關(guān)于jvm gc的文章有很多,寫(xiě)這篇文章不是有什么新東西要講,主要原因是工作時(shí)也偶爾碰到比如ful...
    aaron1993閱讀 1,399評(píng)論 0 0
  • 話說(shuō)今天的朋友圈被一張圖給刷屏了,內(nèi)容正是一份家長(zhǎng)對(duì)于輔導(dǎo)孩子做作業(yè)的吐槽合集。 開(kāi)學(xué)已經(jīng)一個(gè)多月了,經(jīng)過(guò)國(guó)慶8天...
    吹西閱讀 650評(píng)論 5 9

友情鏈接更多精彩內(nèi)容