1、基本概念 heap=young+old,不包括perm區(qū) young=eden + from_survivor + to_survivor,實際可用的大小是eden + to_survivor 串行收集器-單cpu使用,相對高效 并行收集器-多cpu,吞吐量優(yōu)先時使用 并發(fā)收集器-多cpu,停頓時間優(yōu)先時使用(web應用一般用這個) 2、基本JVM參數(shù) -Xmx64m 最大heap大小,默認物理內(nèi)存的1/4(但是限制<1GB) -Xms64m 初始heap大小,默認物理內(nèi)存的1/64(但是限制<1GB) -Xmn12m young代大小,sun推薦整個heap的3/8,太大會減少old的大小,引發(fā)較頻繁的major gc -Xss256k 每個線程的堆棧大小,一般256就ok了 -XX:SurvivorRatio=16 eden與一個survivor的比值,默認是8 -XX:+DisableExplicitGC 關閉System.gc() 3、CMS收集相關參數(shù) -XX:+UseConcMarkSweepGC 使用CMS內(nèi)存收集 -XX:+UseCMSCompactAtFullCollection 在full gc的時候,對old區(qū)壓縮 -XX:CMSFullGCsBeforeCompaction=1 多少次full gc后進行old區(qū)壓縮,cms會產(chǎn)生old區(qū)"碎片",要進行整理,避免沒有連續(xù)空間放大對象而引發(fā)cms failure出現(xiàn) -XX:CMSInitiatingOccupancyFraction=70 old區(qū)使用70%后開始CMS收集,jdk5默認68%,jdk6默認92% -XX:CMSInitiatingPermOccupancyFraction=70 perm區(qū)使用70%后開始CMS收集,jdk5默認68%,jdk6默認92% -XX:+CMSClassUnloadingEnabled 允許perm區(qū)不夠引發(fā)full gc時perm區(qū)的類卸載 -XX:+UseParNewGC 設置年輕代為并行收集 -XX:ParallelGCThreads=4 并行收集器的線程數(shù),此值最好配置與處理器數(shù)目相等 -XX:MaxTenuringThreshold=3 垃圾最大年齡,jdk5之前,cms收集器默認為0,jdk6默認為4 4、GC日志輔助參數(shù) -XX:+PrintGCDetails 輸出gc詳細信息 -XX:+PrintGCTimeStamps 輸出gc時間戳,java 6之后使用-XX:+PrintGCDateStamps,閱讀更方便 -Xloggc:filename gc日志文件路徑 -XX:+PrintTenuringDistribution survivor的對象進入old區(qū)之前進行了幾次copy,與設置的-XX:MaxTenuringThreshold比較,調(diào)整此值和survivor大小 5、各個參數(shù)調(diào)整經(jīng)驗 heap大?。涸诒WCos順暢運轉(zhuǎn)的前提下,heap盡量大。 young區(qū): 盡量大,過小可能引發(fā)頻繁major gc,降低吞吐量,同時可能導致對象直接進入old區(qū),如果old滿了,觸發(fā)full gc; 過大會引起回收耗時過長,導致應用停頓,gui程序不要太大的young區(qū)。 old區(qū): 過大會導致old回收過慢,應用停頓較長(實際上cms回收是很快的,所以盡量大些,減少cms gc頻率); 過小會導致產(chǎn)生old區(qū)小碎片,放不下大對象,引起頻繁full gc。 如果用了緩存,old區(qū)要適當大些,同時緩存不應該無限增長。 young與old的調(diào)整原則:要考慮old區(qū)的耗時、頻率,盡可能降低這兩個值。 6、minor gc,回收young區(qū) 當young代滿了(即eden區(qū)放不下新創(chuàng)建的對象),觸發(fā)minor gc,只回收young區(qū)的對象,old區(qū)不回收。 young區(qū)被回收的對象越多,gc速度越快,因為young區(qū)采用的是“復制”的方式,即把enden區(qū)和survivor的from區(qū)存活對象復制到survivor的to區(qū)。 如果設置了-XX:MaxTenuringThreshold=N參數(shù),survivor的from區(qū)對象到to的復制達到了N次,進入old區(qū),如果to區(qū)裝不下,直接進入old區(qū)。 關于promotion failed: 引發(fā)的兩個原因: 1)survivor太小了,survivor里面的對象還沒有到達進入old的copy次數(shù) 2)進入old區(qū)的對象太多,而old區(qū)已經(jīng)不夠用了 這兩個情況都會引發(fā)full gc,導致停頓較長。 第一個可以調(diào)整survivor的大小,或者直接去掉-XX:MaxTenuringThreshold參數(shù),minor gc回收不掉直接進入old區(qū); 第二個可以調(diào)小young、增大old的大?。ūM早觸發(fā)minor gc,減少每次進入old的對象數(shù)量),或者調(diào)小-XX:CMSInitiatingOccupancyFraction(盡早觸發(fā)old的回收) 7、cms gc,回收old區(qū) 步驟:initial-mark> concurrent-mark> concurrent-preclean> remark> concurrent-sweep> concurrent-reset 除了initial-mark、remark之外,不暫停應用。 關于concurrent mode failure: 引發(fā)的兩個原因 1)年老代變滿之前,old區(qū)垃圾回收還沒有完成 2)新空間分配請求在年老代的剩余空間中無法得到滿足,日志:[GC 90010.628: [ParNew: 261760K->261760K(261952K), 0.0000350secs]90010.628: [CMS (concurrent mode failure) 第一個需要調(diào)小old區(qū),或者調(diào)小參數(shù)-XX:CMSInitiatingOccupancyFraction=70,以盡快回收old區(qū),減少old回收時間; 第二個需要減少young、增加old的大小,或者使用-XX:CMSFullGCsBeforeCompaction并設置較小的值,提高full gc后壓縮old的頻次,避免young大對象無法晉升到old。 |
|