首先需要注意的是在對(duì)JVM內(nèi)存調(diào)優(yōu)的時(shí)候不能只看操作系統(tǒng)級(jí)別Java進(jìn)程所占用的內(nèi)存,這個(gè)數(shù)值不能準(zhǔn)確的反應(yīng)堆內(nèi)存的真實(shí)占用情況,因?yàn)镚C過后這個(gè)值是不會(huì)變化的,因此內(nèi)存調(diào)優(yōu)的時(shí)候要更多地使用JDK提供的內(nèi)存查看工具,比如JConsole和Java VisualVM。
對(duì)JVM內(nèi)存的系統(tǒng)級(jí)的調(diào)優(yōu)主要的目的是減少GC的頻率和Full GC的次數(shù),過多的GC和Full GC是會(huì)占用很多的系統(tǒng)資源(主要是CPU),影響系統(tǒng)的吞吐量。特別要關(guān)注Full GC,因?yàn)樗鼤?huì)對(duì)整個(gè)堆進(jìn)行整理,導(dǎo)致Full GC一般由于以下幾種情況:
● 舊生代空間不足
調(diào)優(yōu)時(shí)盡量讓對(duì)象在新生代GC時(shí)被回收、讓對(duì)象在新生代多存活一段時(shí)間和不要?jiǎng)?chuàng)建過大的對(duì)象及數(shù)組避免直接在舊生代創(chuàng)建對(duì)象
● Pemanet Generation空間不足
增大Perm Gen空間,避免太多靜態(tài)對(duì)象
● 統(tǒng)計(jì)得到的GC后晉升到舊生代的平均大小大于舊生代剩余空間
控制好新生代和舊生代的比例
● System.gc()被顯示調(diào)用
垃圾回收不要手動(dòng)觸發(fā),盡量依靠JVM自身的機(jī)制
調(diào)優(yōu)手段主要是通過控制堆內(nèi)存的各個(gè)部分的比例和GC策略來實(shí)現(xiàn),下面來看看各部分比例不良設(shè)置會(huì)導(dǎo)致什么后果
1)新生代設(shè)置過小
一是新生代GC次數(shù)非常頻繁,增大系統(tǒng)消耗;二是導(dǎo)致大對(duì)象直接進(jìn)入舊生代,占據(jù)了舊生代剩余空間,誘發(fā)Full GC
2)新生代設(shè)置過大
一是新生代設(shè)置過大會(huì)導(dǎo)致舊生代過小(堆總量一定),從而誘發(fā)Full GC;二是新生代GC耗時(shí)大幅度增加
一般說來新生代占整個(gè)堆1/3比較合適
3)Survivor設(shè)置過小
導(dǎo)致對(duì)象從eden直接到達(dá)舊生代,降低了在新生代的存活時(shí)間
4)Survivor設(shè)置過大
導(dǎo)致eden過小,增加了GC頻率
另外,通過-XX:MaxTenuringThreshold=n來控制新生代存活時(shí)間,盡量讓對(duì)象在新生代被回收
由上一篇博文JVM學(xué)習(xí)筆記(三)------內(nèi)存管理和垃圾回收可知新生代和舊生代都有多種GC策略和組合搭配,選擇這些策略對(duì)于我們這些開發(fā)人員是個(gè)難題,JVM提供兩種較為簡單的GC策略的設(shè)置方式
1)吞吐量優(yōu)先
JVM以吞吐量為指標(biāo),自行選擇相應(yīng)的GC策略及控制新生代與舊生代的大小比例,來達(dá)到吞吐量指標(biāo)。這個(gè)值可由-XX:GCTimeRatio=n來設(shè)置
2)暫停時(shí)間優(yōu)先
JVM以暫停時(shí)間為指標(biāo),自行選擇相應(yīng)的GC策略及控制新生代與舊生代的大小比例,盡量保證每次GC造成的應(yīng)用停止時(shí)間都在指定的數(shù)值范圍內(nèi)完成。這個(gè)值可由-XX:MaxGCPauseRatio=n來設(shè)置
最后匯總一下JVM常見配置
堆設(shè)置
-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:設(shè)置年輕代大小
-XX:NewRatio=n:設(shè)置年輕代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代占整個(gè)年輕代年老代和的1/4
-XX:SurvivorRatio=n:年輕代中Eden區(qū)與兩個(gè)Survivor區(qū)的比值。注意Survivor區(qū)有兩個(gè)。如:3,表示Eden:Survivor=3:2,一個(gè)Survivor區(qū)占整個(gè)年輕代的1/5
-XX:MaxPermSize=n:設(shè)置持久代大小
收集器設(shè)置
-XX:+UseSerialGC:設(shè)置串行收集器
-XX:+UseParallelGC:設(shè)置并行收集器
-XX:+UseParalledlOldGC:設(shè)置并行年老代收集器
-XX:+UseConcMarkSweepGC:設(shè)置并發(fā)收集器
垃圾回收統(tǒng)計(jì)信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器設(shè)置
-XX:ParallelGCThreads=n:設(shè)置并行收集器收集時(shí)使用的CPU數(shù)。并行收集線程數(shù)。
-XX:MaxGCPauseMillis=n:設(shè)置并行收集最大暫停時(shí)間
-XX:GCTimeRatio=n:設(shè)置垃圾回收時(shí)間占程序運(yùn)行時(shí)間的百分比。公式為1/(1+n)
并發(fā)收集器設(shè)置
-XX:+CMSIncrementalMode:設(shè)置為增量模式。適用于單CPU情況。
-XX:ParallelGCThreads=n:設(shè)置并發(fā)收集器年輕代收集方式為并行收集時(shí),使用的CPU數(shù)。并行收集線程數(shù)。
相關(guān)鏈接: