第一類內(nèi)存溢出,也是大家認(rèn)為最多,第一反應(yīng)認(rèn)為是的內(nèi)存溢出,就是堆棧溢出:
那什么樣的情況就是堆棧溢出呢?當(dāng)你看到下面的關(guān)鍵字的時(shí)候它就是堆棧溢出了:
java.lang.OutOfMemoryError: ......java heap space.....
也就是當(dāng)你看到heap相關(guān)的時(shí)候就肯定是堆棧溢出了,此時(shí)如果代碼沒(méi)有問(wèn)題的情況下,適當(dāng)調(diào)整-Xmx和-Xms是可以避免的,不過(guò)一定是代碼沒(méi)有問(wèn)題的前提,為什么會(huì)溢出呢,要么代碼有問(wèn)題,要么訪問(wèn)量太多并且每個(gè)訪問(wèn)的時(shí)間太長(zhǎng)或者數(shù)據(jù)太多,導(dǎo)致數(shù)據(jù)釋放不掉,因?yàn)槔厥掌魇且业侥切┦抢拍芑厥?,這里它不會(huì)認(rèn)為這些東西是垃圾,自然不會(huì)去回收了;主意這個(gè)溢出之前,可能系統(tǒng)會(huì)提前先報(bào)錯(cuò)關(guān)鍵字為:
java.lang.OutOfMemoryError:GC over head limit exceeded
這種情況是當(dāng)系統(tǒng)處于高頻的GC狀態(tài),而且回收的效果依然不佳的情況,就會(huì)開(kāi)始報(bào)這個(gè)錯(cuò)誤,這種情況一般是產(chǎn)生了很多不可以被釋放的對(duì)象,有可能是引用使用不當(dāng)導(dǎo)致,或申請(qǐng)大對(duì)象導(dǎo)致,但是java heap space的內(nèi)存溢出有可能提前不會(huì)報(bào)這個(gè)錯(cuò)誤,也就是可能內(nèi)存就直接不夠?qū)е拢皇歉哳lGC.
第二類內(nèi)存溢出,PermGen的溢出,或者PermGen 滿了的提示,你會(huì)看到這樣的關(guān)鍵字:
關(guān)鍵信息為:
java.lang.OutOfMemoryError: PermGen space
原因:系統(tǒng)的代碼非常多或引用的第三方包非常多、或代碼中使用了大量的常量、或通過(guò)intern注入常量、或者通過(guò)動(dòng)態(tài)代碼加載等方法,導(dǎo)致常量池的膨脹,雖然JDK 1.5以后可以通過(guò)設(shè)置對(duì)永久帶進(jìn)行回收,但是我們希望的是這個(gè)地方是不做GC的,它夠用就行,所以一般情況下今年少做類似的操作,所以在面對(duì)這種情況常用的手段是:增加-XX:PermSize和-XX:MaxPermSize的大小。
第三類內(nèi)存溢出:在使用ByteBuffer中的allocateDirect()的時(shí)候會(huì)用到,很多javaNIO的框架中被封裝為其他的方法
溢出關(guān)鍵字:
java.lang.OutOfMemoryError: Direct buffer memory
如果你在直接或間接使用了ByteBuffer中的allocateDirect方法的時(shí)候,而不做clear的時(shí)候就會(huì)出現(xiàn)類似的問(wèn)題,常規(guī)的引用程序IO輸出存在一個(gè)內(nèi)核態(tài)與用戶態(tài)的轉(zhuǎn)換過(guò)程,也就是對(duì)應(yīng)直接內(nèi)存與非直接內(nèi)存,如果常規(guī)的應(yīng)用程序你要將一個(gè)文件的內(nèi)容輸出到客戶端需要通過(guò)OS的直接內(nèi)存轉(zhuǎn)換拷貝到程序的非直接內(nèi)存(也就是heap中),然后再輸出到直接內(nèi)存由操作系統(tǒng)發(fā)送出去,而直接內(nèi)存就是由OS和應(yīng)用程序共同管理的,而非直接內(nèi)存可以直接由應(yīng)用程序自己控制的內(nèi)存,jvm垃圾回收不會(huì)回收掉直接內(nèi)存這部分的內(nèi)存,所以要注意了哦。
如果經(jīng)常有類似的操作,可以考慮設(shè)置參數(shù):-XX:MaxDirectMemorySize
第四類內(nèi)存溢出錯(cuò)誤:
溢出關(guān)鍵字:
java.lang.StackOverflowError
這個(gè)參數(shù)直接說(shuō)明一個(gè)內(nèi)容,就是-Xss太小了,我們申請(qǐng)很多局部調(diào)用的棧針等內(nèi)容是存放在用戶當(dāng)前所持有的線程中的,線程在jdk 1.4以前默認(rèn)是256K,1.5以后是1M,如果報(bào)這個(gè)錯(cuò),只能說(shuō)明-Xss設(shè)置得太小,當(dāng)然有些廠商的JVM不是這個(gè)參數(shù),本文僅僅針對(duì)Hotspot VM而已;不過(guò)在有必要的情況下可以對(duì)系統(tǒng)做一些優(yōu)化,使得-Xss的值是可用的。
第五類內(nèi)存溢出錯(cuò)誤:
溢出關(guān)鍵字:
java.lang.OutOfMemoryError: unable to create new native thread
上面第四種溢出錯(cuò)誤,已經(jīng)說(shuō)明了線程的內(nèi)存空間,其實(shí)線程基本只占用heap以外的內(nèi)存區(qū)域,也就是這個(gè)錯(cuò)誤說(shuō)明除了heap以外的區(qū)域,無(wú)法為線程分配一塊內(nèi)存區(qū)域了,這個(gè)要么是內(nèi)存本身就不夠,要么heap的空間設(shè)置得太大了,導(dǎo)致了剩余的內(nèi)存已經(jīng)不多了,而由于線程本身要占用內(nèi)存,所以就不夠用了,說(shuō)明了原因,如何去修改,不用我多說(shuō),你懂的。
第六類內(nèi)存溢出:
溢出關(guān)鍵字
java.lang.OutOfMemoryError: request {} byte for {}out of swap
這類錯(cuò)誤一般是由于地址空間不夠而導(dǎo)致。
六大類常見(jiàn)溢出已經(jīng)說(shuō)明JVM中99%的溢出情況,要逃出這些溢出情況非常困難,除非一些很怪異的故障問(wèn)題會(huì)發(fā)生,比如由于物理內(nèi)存的硬件問(wèn)題,導(dǎo)致了code cache的錯(cuò)誤(在由byte code轉(zhuǎn)換為native code的過(guò)程中出現(xiàn),但是概率極低),這種情況內(nèi)存 會(huì)被直接crash掉,類似還有swap的頻繁交互在部分系統(tǒng)中會(huì)導(dǎo)致系統(tǒng)直接被crash掉,OS地址空間不夠的話,系統(tǒng)根本無(wú)法啟動(dòng),呵呵;JNI的濫用也會(huì)導(dǎo)致一些本地內(nèi)存無(wú)法釋放的問(wèn)題,所以盡量避開(kāi)JNI;socket連接數(shù)據(jù)打開(kāi)過(guò)多的socket也會(huì)報(bào)類似:IOException: Too many open files等錯(cuò)誤信息。
JNI就不用多說(shuō)了,盡量少用,除非你的代碼太牛B了,我無(wú)話可說(shuō),呵呵,這種內(nèi)存如果沒(méi)有在被調(diào)用的語(yǔ)言內(nèi)部將內(nèi)存釋放掉(如C語(yǔ)言),那么在進(jìn)程結(jié)束前這些內(nèi)存永遠(yuǎn)釋放不掉,解決辦法只有一個(gè)就是將進(jìn)程kill掉。
另外GC本身是需要內(nèi)存空間的,因?yàn)樵谶\(yùn)算和中間數(shù)據(jù)轉(zhuǎn)換過(guò)程中都需要有內(nèi)存,所以你要保證GC的時(shí)候有足夠的內(nèi)存哦,如果沒(méi)有的話GC的過(guò)程將會(huì)非常的緩慢。
順便這里就提及一些新的CMS GC的內(nèi)容和策略(有點(diǎn)亂,每次寫(xiě)都很亂,但是能看多少看多少吧):
首先我再寫(xiě)一次一前博客中的已經(jīng)寫(xiě)過(guò)的內(nèi)容,就是很多參數(shù)沒(méi)啥建議值,建議值是自己在現(xiàn)場(chǎng)根據(jù)實(shí)際情況科學(xué)計(jì)算和測(cè)試得到的綜合效果,建議值沒(méi)有絕對(duì)好的,而且默認(rèn)值很多也是有問(wèn)題的,因?yàn)椴煌陌姹竞蛷S商都有很大的區(qū)別,默認(rèn)值沒(méi)有永久都是一樣的,就像-Xss參數(shù)的變化一樣,要看到你當(dāng)前的java程序heap的大致情況可以這樣看看(以下參數(shù)是隨便設(shè)置的,并不是什么默認(rèn)值):
$sudo jmap -heap `pgrep java`
Attaching to process ID 4280, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 19.1-b02
using thread-local object allocation.
Parallel GC with 8 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 134217728 (128.0MB)
MaxNewSize = 134217728 (128.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 134217728 (128.0MB)
MaxPermSize = 268435456 (256.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 85721088 (81.75MB)
used = 22481312 (21.439849853515625MB)
free = 63239776 (60.310150146484375MB)
26.22611602876529% used
From Space:
capacity = 24051712 (22.9375MB)
used = 478488 (0.45632171630859375MB)
free = 23573224 (22.481178283691406MB)
1.9894134770946867% used
To Space:
capacity = 24248320 (23.125MB)
used = 0 (0.0MB)
free = 24248320 (23.125MB)
0.0% used
PS Old Generation
capacity = 939524096 (896.0MB)
used = 16343864 (15.586723327636719MB)
free = 923180232 (880.4132766723633MB)
1.7395896571023124% used
PS Perm Generation
capacity = 134217728 (128.0MB)
used = 48021344 (45.796722412109375MB)
free = 86196384 (82.20327758789062MB)
35.77868938446045% used
付:sudo是需要拿到管理員權(quán)限,如果你的系統(tǒng)權(quán)限很大那么就不需要了,最后的grep java那個(gè)內(nèi)容如果不對(duì),可以直接通過(guò)jps或者ps命令將和java相關(guān)的進(jìn)程號(hào)直接寫(xiě)進(jìn)去,如:java -map 4280,這個(gè)參數(shù)其實(shí)完全可以通過(guò)jstat工具來(lái)替代,而且看到的效果更加好,這個(gè)參數(shù)在線上應(yīng)用中,盡量少用(尤其是高并發(fā)的應(yīng)用中),可能會(huì)觸發(fā)JVM的bug,導(dǎo)致應(yīng)用掛起;在jvm 1.6u14后可以編寫(xiě)任意一段程序,然后在運(yùn)行程序的時(shí)候,增加參數(shù)為:-XX:+PrintFlagsFinal來(lái)輸出當(dāng)前JVM中運(yùn)行時(shí)的參數(shù)值,或者通過(guò)jinfo來(lái)查看,jinfo是非常強(qiáng)大的工具,可以對(duì)部分參數(shù)進(jìn)行動(dòng)態(tài)修改,當(dāng)然內(nèi)存相關(guān)的東西是不能修改的,只能增加一些不是很相關(guān)的參數(shù),有關(guān)JVM的工具使用,后續(xù)文章中如果有機(jī)會(huì)我們?cè)賮?lái)探討,不是本文的重點(diǎn);補(bǔ)充:關(guān)于參數(shù)的默認(rèn)值對(duì)不同的JVM版本、不同的廠商、運(yùn)行于不同的環(huán)境(一般和位數(shù)有關(guān)系)默認(rèn)值會(huì)有區(qū)別。
OK,再說(shuō)下反復(fù)的一句,沒(méi)有必要的話就不要亂設(shè)置參數(shù),參數(shù)不是拿來(lái)玩的,默認(rèn)的參數(shù)對(duì)于這門JDK都是有好處的,關(guān)鍵是否適合你的應(yīng)用場(chǎng)景,一般來(lái)講你常規(guī)的只需要設(shè)置以下幾個(gè)參數(shù)就可以了:
-server 表示為服務(wù)器端,會(huì)提供很多服務(wù)器端默認(rèn)的配置,如并行回收,而服務(wù)器上一般這個(gè)參數(shù)都是默認(rèn)的,所以都是可以省掉,與之對(duì)應(yīng)的還有一個(gè)-client參數(shù),一般在64位機(jī)器上,JVM是默認(rèn)啟動(dòng)-server參數(shù),也就是默認(rèn)啟動(dòng)并行GC的,但是是ParallelGC而不是ParallelOldGC,兩者算法不同(后面會(huì)簡(jiǎn)單說(shuō)明下),而比較特殊的是windows 32位上默認(rèn)是-client,這兩個(gè)的區(qū)別不僅僅是默認(rèn)的參數(shù)不一樣,在jdk包下的jre包下一般會(huì)包含client和server包,下面分別對(duì)應(yīng)啟動(dòng)的動(dòng)態(tài)鏈接庫(kù),而真正看到的java、javac等相關(guān)命令指示一個(gè)啟動(dòng)導(dǎo)向,它只是根據(jù)命令找到對(duì)應(yīng)的JVM并傳入jvm中進(jìn)行啟動(dòng),也就是看到的java.exe這些文件并不是jvm;說(shuō)了這么多,最終總結(jié)一下就是,-server和-client就是完全不同的兩套VM,一個(gè)用于桌面應(yīng)用,一個(gè)用于服務(wù)器的。
-Xmx 為Heap區(qū)域的最大值
-Xms 為Heap區(qū)域的初始值,線上環(huán)境需要與-Xmx設(shè)置為一致,否則capacity的值會(huì)來(lái)回飄動(dòng),飄得你心曠神怡,你懂的。
-Xss(或-ss) 這個(gè)其實(shí)也是可以默認(rèn)的,如果你真的覺(jué)得有設(shè)置的必要,你就改下吧,1.5以后是1M的默認(rèn)大小(指一個(gè)線程的native空間),如果代碼不多,可以設(shè)置小點(diǎn)來(lái)讓系統(tǒng)可以接受更大的內(nèi)存。注意,還有一個(gè)參數(shù)是-XX:ThreadStackSize,這兩個(gè)參數(shù)在設(shè)置的過(guò)程中如果都設(shè)置是有沖突的,一般按照J(rèn)VM常理來(lái)說(shuō),誰(shuí)設(shè)置在后面,就以誰(shuí)為主,但是最后發(fā)現(xiàn)如果是在1.6以上的版本,-Xss設(shè)置在后面的確都是以-Xss為主,但是要是-XX:ThreadStackSize設(shè)置在后面,主線程還是為-Xss為主,而其它線程以-XX:ThreadStackSize為主,主線程做了一個(gè)特殊判定處理;單獨(dú)設(shè)置都是以本身為主,-Xss不設(shè)置也不會(huì)采用其默認(rèn)值,除非兩個(gè)都不設(shè)置會(huì)采用-Xss的默認(rèn)值。另外這個(gè)參數(shù)針對(duì)于hotspot的vm,在IBM的jvm中,還有一個(gè)參數(shù)為-Xoss,主要原因是IBM在對(duì)棧的處理上有操作數(shù)棧和方法棧等各種不同的棧種類,而hotspot不管是什么棧都放在一個(gè)私有的線程內(nèi)部的,不區(qū)分是什么棧,所以只需要設(shè)置一個(gè)參數(shù),而IBM的J9不是這樣的;有關(guān)棧上的細(xì)節(jié),后續(xù)我們有機(jī)會(huì)專門寫(xiě)文章來(lái)說(shuō)明。
-XX:PermSize與-XX:MaxPermSize兩個(gè)包含了class的裝載的位置,或者說(shuō)是方法區(qū)(但不是本地方法區(qū)),在Hotspot默認(rèn)情況下為64M,主意全世界的JVM只有hostpot的VM才有Perm的區(qū)域,或者說(shuō)只有hotspot才有對(duì)用戶可以設(shè)置的這塊區(qū)域,其他的JVM都沒(méi)有,其實(shí)并不是沒(méi)有這塊區(qū)域,而是這塊區(qū)域沒(méi)有讓用戶來(lái)設(shè)置,其實(shí)這塊區(qū)域本身也不應(yīng)該讓用戶來(lái)設(shè)置,我們也沒(méi)有一個(gè)明確的說(shuō)法這塊空間必須要設(shè)置多大,都是拍腦袋設(shè)置一個(gè)數(shù)字,如果發(fā)布到線上看下如果用得比較多,就再多點(diǎn),如果用的少,就減少點(diǎn),而這塊區(qū)域和性能關(guān)鍵沒(méi)有多大關(guān)系,只要能裝下就OK,并且時(shí)不時(shí)會(huì)因?yàn)镻erm不夠而導(dǎo)致Full GC,所以交給開(kāi)發(fā)者來(lái)調(diào)節(jié)這個(gè)參數(shù)不知道是怎么想的;所以O(shè)racle將在新一代JVM中將這個(gè)區(qū)域徹底刪掉,也就是對(duì)用戶透明,G1的如果真正穩(wěn)定起來(lái),以后JVM的啟動(dòng)參數(shù)將會(huì)非常簡(jiǎn)單,而且理論上管理再大的內(nèi)存也是沒(méi)有問(wèn)題的,其實(shí)G1(garbage first,一種基于region的垃圾收集回收器)已經(jīng)在hotspot中開(kāi)始有所試用,不過(guò)目前效果不好,還不如CMS呢,所以只是試用,G1已經(jīng)作為ORACLE對(duì)JVM研發(fā)的最高重點(diǎn),CMS自現(xiàn)在最高版本后也不再有新功能(可以修改bug),該項(xiàng)目已經(jīng)進(jìn)行5年,尚未發(fā)布正式版,CMS是四五年前發(fā)布的正式版,但是是最近一兩年才開(kāi)始穩(wěn)定,而G1的復(fù)雜性將會(huì)遠(yuǎn)遠(yuǎn)超越CMS,所以要真正使用上G1還有待考察,全世界目前只有IBM J9真正實(shí)現(xiàn)了G1論文中提到的思想(論文于05年左右發(fā)表),IBM已經(jīng)將J9應(yīng)用于websphere中,但是并不代表這是全世界最好的jvm,全世界最好的jvm是Azul(無(wú)停頓垃圾回收算法和一個(gè)零開(kāi)銷的診斷/監(jiān)控工具),幾乎可以說(shuō)這個(gè)jvm是沒(méi)有暫停的,在全世界很多頂尖級(jí)的公司使用,不過(guò)價(jià)格非常貴,不能直接使用,目前這個(gè)jvm的主導(dǎo)者在研究JRockit,而目前hotspot和JRockit都是Oracle的,所以他們可能會(huì)合并,所以我們應(yīng)該對(duì)JVM的性能充滿信心。
也就是說(shuō)你常用的情況下只需要設(shè)置4個(gè)參數(shù)就OK了,除非你的應(yīng)用有些特殊,否則不要亂改,那么來(lái)看看一些其他情況的參數(shù)吧:
先來(lái)看個(gè)不大常用的,就是大家都知道JVM新的對(duì)象應(yīng)該說(shuō)幾乎百分百的在Eden里面,除非Eden真的裝不下,我們不考慮這種變態(tài)的問(wèn)題,因?yàn)榫€上環(huán)境Eden區(qū)域都是不小的,來(lái)降低GC的次數(shù)以及全局 GC的概率;而JVM習(xí)慣將內(nèi)存按照較為連續(xù)的位置進(jìn)行分配,這樣使得有足夠的內(nèi)存可以被分配,減少碎片,那么對(duì)于內(nèi)存最后一個(gè)位置必然就有大量的征用問(wèn)題,JVM在高一點(diǎn)的版本里面提出了為每個(gè)線程分配一些私有的區(qū)域來(lái)做來(lái)解決這個(gè)問(wèn)題,而1.5后的版本還可以動(dòng)態(tài)管理這些區(qū)域,那么如何自己設(shè)置和查看這些區(qū)域呢,看下英文全稱為:Thread Local Allocation Buffer,簡(jiǎn)稱就是:TLAB,即內(nèi)存本地的持有的buffer,設(shè)置參數(shù)有:
-XX:+UseTLAB 啟用這種機(jī)制的意思
-XX:TLABSize=<size in kb> 設(shè)置大小,也就是本地線程中的私有區(qū)域大?。ㄖ挥羞@個(gè)區(qū)域放不下才會(huì)到Eden中去申請(qǐng))。
-XX:+ResizeTLAB 是否啟動(dòng)動(dòng)態(tài)修改
這幾個(gè)參數(shù)在多CPU下非常有用。
-XX:+PrintTLAB 可以輸出TLAB的內(nèi)容。
下面再閑扯些其它的參數(shù):
如果你需要對(duì)Yong區(qū)域進(jìn)行并行回收應(yīng)該如何修改呢?在jdk1.5以后可以使用參數(shù):
-XX:+UseParNewGC
注意: 與它沖突的參數(shù)是:-XX:+UseParallelOldGC和-XX:+UseSerialGC,如果需要用這個(gè)參數(shù),又想讓整個(gè)區(qū)域是并行回收的,那么就使用-XX:+UseConcMarkSweepGC參數(shù)來(lái)配合,其實(shí)這個(gè)參數(shù)在使用了CMS后,默認(rèn)就會(huì)啟動(dòng)該參數(shù),也就是這個(gè)參數(shù)在CMS GC下是無(wú)需設(shè)置的,后面會(huì)提及到這些參數(shù)。
默認(rèn)服務(wù)器上的對(duì)Full并行GC策略為(這個(gè)時(shí)候Yong空間回收的時(shí)候啟動(dòng)PSYong算法,也是并行回收的):
-XX:+UseParallelGC
另外,在jdk1.5后出現(xiàn)一個(gè)新的參數(shù)如下,這個(gè)對(duì)Yong的回收算法和上面一樣,對(duì)Old區(qū)域會(huì)有所區(qū)別,上面對(duì)Old回收的過(guò)程中會(huì)做一個(gè)全局的Compact,也就是全局的壓縮操作,而下面的算法是局部壓縮,為什么要局部壓縮呢?是因?yàn)镴VM發(fā)現(xiàn)每次壓縮后再邏輯上數(shù)據(jù)都在Old區(qū)域的左邊位置,申請(qǐng)的時(shí)候從左向右申請(qǐng),那么生命力越長(zhǎng)的對(duì)象就一般是靠左的,所以它認(rèn)為左邊的對(duì)象就是生命力很強(qiáng),而且較為密集的,所以它針對(duì)這種情況進(jìn)行部分密集,但是這兩種算法mark階段都是會(huì)暫停的,而且存活的對(duì)象越多活著的越多;而ParallelOldGC會(huì)進(jìn)行部分壓縮算法(主意一點(diǎn),最原始的copy算法是不需要經(jīng)過(guò)mark階段,因?yàn)橹恍枰业揭粋€(gè)或活著的就只需要做拷貝就可以,而Yong區(qū)域借用了Copy算法,只是唯一的區(qū)別就是傳統(tǒng)的copy算法是采用兩個(gè)相同大小的內(nèi)存來(lái)拷貝,浪費(fèi)空間為50%,所以分代的目標(biāo)就是想要實(shí)現(xiàn)很多優(yōu)勢(shì)所在,認(rèn)為新生代85%以上的對(duì)象都應(yīng)該是死掉的,所以S0和S1一般并不是很大),該算法為jdk 1.5以后對(duì)于絕大部分應(yīng)用的最佳選擇。
-XX:+UseParallelOldGC
-XX:ParallelGCThread=12:并行回收的線程數(shù),最好根據(jù)實(shí)際情況而定,因?yàn)榫€程多往往存在征用調(diào)度和上下文切換的開(kāi)銷;而且也并非CPU越多線程數(shù)也可以設(shè)置越大,一般設(shè)置為12就再增加用處也不大,主要是算法本身內(nèi)部的征用會(huì)導(dǎo)致其線程的極限就是這樣。
設(shè)置Yong區(qū)域大?。?/span>
-Xmn Yong區(qū)域的初始值和最大值一樣大
-XX:NewSize和-XX:MaxNewSize如果設(shè)置以為一樣大就是和-Xmn,在JRockit中會(huì)動(dòng)態(tài)變化這些參數(shù),根據(jù)實(shí)際情況有可能會(huì)變化出兩個(gè)Yong區(qū)域,或者沒(méi)有Yong區(qū)域,有些時(shí)候會(huì)生出來(lái)一個(gè)半長(zhǎng)命對(duì)象區(qū)域;這里除了這幾個(gè)參數(shù)外,還有一個(gè)參數(shù)是NewRatio是設(shè)置Old/Yong的倍數(shù)的,這幾個(gè)參數(shù)都是有沖突的,服務(wù)器端建議是設(shè)置-Xmn就可以了,如果幾個(gè)參數(shù)全部都有設(shè)置,-Xmn和-XX:NewSize與-XX:MaxNewSize將是誰(shuí)設(shè)置在后面,以誰(shuí)的為準(zhǔn),而-XX:NewSize -XX:MaxNewSize與-XX:NewRatio時(shí),那么參數(shù)設(shè)置的結(jié)果可能會(huì)以下這樣的(jdk 1.4.1后):
min(MaxNewSize,max(NewSize, heap/(NewRatio+1)))
-XX:NewRatio為Old區(qū)域?yàn)閅ong的多少倍,間接設(shè)置Yong的大小,1.6中如果使用此參數(shù),則默認(rèn)會(huì)在適當(dāng)時(shí)候被動(dòng)態(tài)調(diào)整,具體請(qǐng)看下面參數(shù)UseAdaptiveSizepollcy 的說(shuō)明。
三個(gè)參數(shù)不要同時(shí)設(shè)置,因?yàn)槎际窃O(shè)置Yong的大小的。
-XX:SurvivorRatio:該參數(shù)為Eden與兩個(gè)求助空間之一的比例,注意Yong的大小等價(jià)于Eden + S0 + S1,S0和S1的大小是等價(jià)的,這個(gè)參數(shù)為Eden與其中一個(gè)S區(qū)域的大小比例,如參數(shù)為8,那么Eden就占用Yong的80%,而S0和S1分別占用10%。
以前的老版本有一個(gè)參數(shù)為:-XX:InitialSurivivorRatio,如果不做任何設(shè)置,就會(huì)以這個(gè)參數(shù)為準(zhǔn),這個(gè)參數(shù)的默認(rèn)值就是8,不過(guò)這個(gè)參數(shù)并不是Eden/Survivor的大小,而是Yong/Survivor,所以所以默認(rèn)值8,代表每一個(gè)S區(qū)域的空間大小為Yong區(qū)域的12.5%而不是10%。另外順便提及一下,每次大家看到GC日志的時(shí)候,GC日志中的每個(gè)區(qū)域的最大值,其中Yong的空間最大值,始終比設(shè)置的Yong空間的大小要小一點(diǎn),大概是小12.5%左右,那是因?yàn)槊看慰捎每臻g為Eden加上一個(gè)Survivor區(qū)域的大小,而不是整個(gè)Yong的大小,因?yàn)榭捎每臻g每次最多是這樣大,兩個(gè)Survivor區(qū)域始終有一塊是空的,所以不會(huì)加上兩個(gè)來(lái)計(jì)算。
-XX:MaxTenuringThreshold=15:在正常情況下,新申請(qǐng)的對(duì)象在Yong區(qū)域發(fā)生多少次GC后就會(huì)被移動(dòng)到Old(非正常就是S0或S1放不下或者不太可能出現(xiàn)的Eden都放不下的對(duì)象),這個(gè)參數(shù)一般不會(huì)超過(guò)16(因?yàn)橛?jì)數(shù)器從0開(kāi)始計(jì)數(shù),所以設(shè)置為15的時(shí)候相當(dāng)于生命周期為16)。
要查看現(xiàn)在的這個(gè)值的具體情況,可以使用參數(shù):-XX:+PrintTenuringDistribution
通過(guò)上面的jmap應(yīng)該可以看出我的機(jī)器上的MinHeapFreeRatio和MaxHeapFreeRatio分別為40個(gè)70,也就是大家經(jīng)常說(shuō)的在GC后剩余空間小于40%時(shí)capacity開(kāi)始增大,而大于70%時(shí)減小,由于我們不希望讓它移動(dòng),所以這兩個(gè)參數(shù)幾乎沒(méi)有意義,如果你需要設(shè)置就設(shè)置參數(shù)為:
-XX:MinHeapFreeRatio=40
-XX:MaxHeapFreeRatio=70
JDK 1.6后有一個(gè)動(dòng)態(tài)調(diào)節(jié)板塊的,當(dāng)然如果你的每一個(gè)板塊都是設(shè)置固定值,這個(gè)參數(shù)也沒(méi)有用,不過(guò)如果是非固定的,建議還是不要?jiǎng)討B(tài)調(diào)整,默認(rèn)是開(kāi)啟的,建議將其關(guān)掉,參數(shù)為:
-XX:+UseAdaptiveSizepollcy 建議使用-XX:-UseAdaptiveSizepollcy關(guān)掉,為什么當(dāng)你的參數(shù)設(shè)置了NewRatio、Survivor、MaxTenuringThreshold這幾個(gè)參數(shù)如果在啟動(dòng)了動(dòng)態(tài)更新情況下,是無(wú)效的,當(dāng)然如果你設(shè)置-Xmn是有效的,但是如果設(shè)置的比例的話,初始化可能會(huì)按照你的參數(shù)去運(yùn)行,不過(guò)運(yùn)行過(guò)程中會(huì)通過(guò)一定的算法動(dòng)態(tài)修改,監(jiān)控中你可能會(huì)發(fā)現(xiàn)這些參數(shù)會(huì)發(fā)生改變,甚至于S0和S1的大小不一樣。
如果啟動(dòng)了這個(gè)參數(shù),又想要跟蹤變化,那么就使用參數(shù):-XX:+PrintAdaptiveSizePolicy
上面已經(jīng)提到,javaNIO中通過(guò)Direct內(nèi)存來(lái)提高性能,這個(gè)區(qū)域的大小默認(rèn)是64M,在適當(dāng)?shù)膱?chǎng)景可以設(shè)置大一些。
-XX:MaxDirectMemorySize
一個(gè)不太常用的參數(shù):
-XX:+ScavengeBeforeFullGC 默認(rèn)是開(kāi)啟狀態(tài),在full GC前先進(jìn)行minor GC。
對(duì)于java堆中如果要設(shè)置大頁(yè)內(nèi)存,可以通過(guò)設(shè)置參數(shù):
付:此參數(shù)必須在操作系統(tǒng)的內(nèi)核支持的基礎(chǔ)上,需要在OS級(jí)別做操作為:
echo 1024 > /proc/sys/vm/nr_hugepages
echo 2147483647 > /proc/sys/kernel/shmmax
-XX:+UseLargePages
-XX:LargePageSizeInBytes
此時(shí)整個(gè)JVM都將在這塊內(nèi)存中,否則全部不在這塊內(nèi)存中。
javaIO的臨時(shí)目錄設(shè)置
-Djava.io.tmpdir
jstack會(huì)去尋找/tmp/hsperfdata_admin下去尋找與進(jìn)程號(hào)相同的文件,32位機(jī)器上是沒(méi)有問(wèn)題的,64為機(jī)器的是有BUG的,在jdk 1.6u23版本中已經(jīng)修復(fù)了這個(gè)bug,如果你遇到這個(gè)問(wèn)題,就需要升級(jí)JDK了。
還記得上次說(shuō)的平均晉升大小嗎,在并行GC時(shí),如果平均晉升大小大于old剩余空間,則發(fā)生full GC,那么當(dāng)小于剩余空間時(shí),也就是平均晉升小于剩余空間,但是剩余空間小于eden + 一個(gè)survivor的空間時(shí),此時(shí)就依賴于參數(shù):
-XX:-HandlePromotionFailure
啟動(dòng)該參數(shù)時(shí),上述情況成立就發(fā)生minor gc(YGC),大于則發(fā)生full gc(major gc)。
一般默認(rèn)直接分配的對(duì)象如果大于Eden的一半就會(huì)直接晉升到old區(qū)域,但是也可以通過(guò)參數(shù)來(lái)指定:
-XX:PretenureSizeThreshold=2m 我個(gè)人不建議使用這個(gè)參數(shù)
也就是當(dāng)申請(qǐng)對(duì)象大于這個(gè)值就會(huì)晉升到old區(qū)域。
傳說(shuō)中GC時(shí)間的限制,一個(gè)是通過(guò)比例限制,一個(gè)是通過(guò)最大暫停時(shí)間限制,但是GC時(shí)間能限制么,呵呵,在增量中貌似可以限制,不過(guò)不能限制住GC總體的時(shí)間,所以這個(gè)參數(shù)也不是那么關(guān)鍵。
-XX:GCTimeRatio=
-XX:MaxGCPauseMillis
-XX:GCTimeLimit
要看到真正暫停的時(shí)間就一個(gè)是看GCDetail的日志,另一個(gè)是設(shè)置參數(shù)看:
-XX:+PrintGCApplicationStoppedTime
有些人,有些人就是喜歡在代碼里面里頭寫(xiě)System.gc(),???,這個(gè)不是測(cè)試程序是線上業(yè)務(wù),這樣將會(huì)導(dǎo)致N多的問(wèn)題,不多說(shuō)了,你應(yīng)該懂的,不懂的話看下書(shū)吧,而RMI是很不聽(tīng)話的一個(gè)鳥(niǎo)玩意,EJB的框架也是基于RMI寫(xiě)的,RMI為什么不聽(tīng)話呢,就是它自己在里面非要搞個(gè)System.gc(),哎,為了放置頻繁的做,頻繁的做,你就將這個(gè)命令的執(zhí)行禁用掉吧,當(dāng)然程序不用改,不然那些EJB都跑步起來(lái)了,呵呵:
-XX:+DisableExplicitGC 默認(rèn)是沒(méi)有禁用掉,寫(xiě)成+就是禁用掉的了,但是有些時(shí)候在使用allocateDirect的時(shí)候,很多時(shí)候還真需要System.gc來(lái)強(qiáng)制回收這塊資源。
內(nèi)存溢出時(shí)導(dǎo)出溢出的錯(cuò)誤信息:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/xieyu/logs/ 這個(gè)參數(shù)指定導(dǎo)出時(shí)的路徑,不然導(dǎo)出的路徑就是虛擬機(jī)的目標(biāo)位置,不好找了,默認(rèn)的文件名是:java_pid<進(jìn)程號(hào)>.hprof,這個(gè)文件可以類似使用jmap -dump:file=....,format=b <pid>來(lái)dump類似的內(nèi)容,文件后綴都是hprof,然后下載mat工具進(jìn)行分析即可(不過(guò)內(nèi)存有多大dump文件就多大,而本地分析的時(shí)候內(nèi)存也需要那么大,所以很多時(shí)候下載到本地都無(wú)法啟動(dòng)是很正常的),后續(xù)文章有機(jī)會(huì)我們來(lái)說(shuō)明這些工具,另外jmap -dump參數(shù)也不要經(jīng)常用,會(huì)導(dǎo)致應(yīng)用掛起哦;另外此參數(shù)只會(huì)在第一次輸出OOM的時(shí)候才會(huì)進(jìn)行堆的dump操作(java heap的溢出是可以繼續(xù)運(yùn)行再運(yùn)行的程序的,至于web應(yīng)用是否服務(wù)要看應(yīng)用服務(wù)器自身如何處理,而c heap區(qū)域的溢出就根本沒(méi)有dump的機(jī)會(huì),因?yàn)橹苯泳湾礄C(jī)了,目前系統(tǒng)無(wú)法看到c heap的大小以及內(nèi)部變化,要看大小只能間接通過(guò)看JVM進(jìn)程的內(nèi)存大小(top或類似參數(shù)),這個(gè)大小一般會(huì)大于heap+perm的大小,多余的部分基本就可以認(rèn)為是c heap的大小了,而看內(nèi)部變化呢只有google perftools可以達(dá)到這個(gè)目的),如果內(nèi)存過(guò)大這個(gè)dump操作將會(huì)非常長(zhǎng),所以hotspot如果以后想管理大內(nèi)存,這塊必須有新的辦法出來(lái)。
最后,用dump出來(lái)的文件,通過(guò)mat分析出來(lái)的結(jié)果往往有些時(shí)候難以直接確定到底哪里有問(wèn)題,可以看到的維度大概有:那個(gè)類使用的內(nèi)存最多,以及每一個(gè)線程使用的內(nèi)存,以及線程內(nèi)部每一個(gè)調(diào)用的類和方法所使用的內(nèi)存,但是很多時(shí)候無(wú)法判定到底是程序什么地方調(diào)用了這個(gè)類或者方法,因?yàn)檫@里只能看到最終消耗內(nèi)存的類,但是不知道誰(shuí)使用了它,一個(gè)辦法是掃描代碼,但是太笨重,而且如果是jar包中調(diào)用了就不好弄了,另一種方法是寫(xiě)agent,那么就需要相應(yīng)的配合了,但是有一個(gè)非常好的工具就是btrace工具(jdk 1.7貌似還不支持),可以跟蹤到某個(gè)類的某個(gè)方法被那些類中的方法調(diào)用過(guò),那這個(gè)問(wèn)題就好說(shuō)了,只要知道開(kāi)銷內(nèi)存的是哪一個(gè)類,就能知道誰(shuí)調(diào)用過(guò)它,OK,關(guān)于btrace的不是本文重點(diǎn),網(wǎng)上都有,后續(xù)文章有機(jī)會(huì)再探討,
原理:
No performance impact during runtime(無(wú)性能影響)
Dumping a –Xmx512m heap
Create a 512MB .hprof file(512M內(nèi)存就dump出512M的空間大小)
JVM is “dead” during dumping(死掉時(shí)dump)
Restarting JVM during this dump will cause unusable .hprof file(重啟導(dǎo)致文件不可用)
注明的NUMA架構(gòu),在JVM中開(kāi)始支持,當(dāng)然也需要CPU和OS的支持才可以,需要設(shè)置參數(shù)為:
-XX:+UseNUMA 必須在并行GC的基礎(chǔ)上才有的
老年代無(wú)法分配區(qū)域的最大等待時(shí)間為(默認(rèn)值為0,但是也不要去動(dòng)它):
-XX:GCExpandToAllocateDelayMillis
讓JVM中所有的set和get方法轉(zhuǎn)換為本地代碼:
-XX:+UseFastAccessorMethods
以時(shí)間戳輸出Heap的利用率
-XX:+PrintHeapUsageOverTime
在64bit的OS上面(其實(shí)一般達(dá)不到57位左右),由于指針會(huì)放大為8個(gè)byte,所以會(huì)導(dǎo)致空間使用增加,當(dāng)然,如果內(nèi)存夠大,就沒(méi)有問(wèn)題,但是如果升級(jí)到64bit系統(tǒng)后,只是想讓內(nèi)存達(dá)到4G或者8G,那么就完全可以通過(guò)很多指針壓縮為4byte就OK了,所以在提供以下參數(shù)(本參數(shù)于jdk 1.6u23后使用,并自動(dòng)開(kāi)啟,所以也不需要你設(shè)置,知道就OK):
-XX:+UseCompressedOops 請(qǐng)注意:這個(gè)參數(shù)默認(rèn)在64bit的環(huán)境下默認(rèn)啟動(dòng),但是如果JVM的內(nèi)存達(dá)到32G后,這個(gè)參數(shù)就會(huì)默認(rèn)為不啟動(dòng),因?yàn)?2G內(nèi)存后,壓縮就沒(méi)有多大必要了,要管理那么大的內(nèi)存指針也需要很大的寬度了。
后臺(tái)JIT編譯優(yōu)化啟動(dòng)
-XX:+BackgroundCompilation
如果你要輸出GC的日志以及時(shí)間戳,相關(guān)的參數(shù)有:
-XX:+PrintGCDetails 輸出GC的日志詳情,包含了時(shí)間戳
-XX:+PrintGCTimeStamps 輸出GC的時(shí)間戳信息,按照啟動(dòng)JVM后相對(duì)時(shí)間的每次GC的相對(duì)秒值(毫秒在小數(shù)點(diǎn)后面),也就是每次GC相對(duì)啟動(dòng)JVM啟動(dòng)了多少秒后發(fā)生了這次GC
-XX:+PrintGCDateStamps輸出GC的時(shí)間信息,會(huì)按照系統(tǒng)格式的日期輸出每次GC的時(shí)間
-XX:+PrintGCTaskTimeStamps輸出任務(wù)的時(shí)間戳信息,這個(gè)細(xì)節(jié)上比較復(fù)雜,后續(xù)有文章來(lái)探討。
-XX:-TraceClassLoading 跟蹤類的裝載
-XX:-TraceClassUnloading 跟蹤類的卸載
-XX:+PrintHeapAtGC 輸出GC后各個(gè)堆板塊的大小。
將常量信息GC信息輸出到日志文件:
-Xloggc:/home/xieyu/logs/gc.log
現(xiàn)在面對(duì)大內(nèi)存比較流行是是CMS GC(最少1.5才支持),首先明白CMS的全稱是什么,不是傳統(tǒng)意義上的內(nèi)容管理系統(tǒng)(Content Management System)哈,第一次我也沒(méi)看懂,它的全稱是:Concurrent Mark Sweep,三個(gè)單詞分別代表并發(fā)、標(biāo)記、清掃(主意這里沒(méi)有compact操作,其實(shí)CMS GC的確沒(méi)有compact操作),也就是在程序運(yùn)行的同時(shí)進(jìn)行標(biāo)記和清掃工作,至于它的原理前面有提及過(guò),只是有不同的廠商在上面做了一些特殊的優(yōu)化,比如一些廠商在標(biāo)記根節(jié)點(diǎn)的過(guò)程中,標(biāo)記完當(dāng)前的根,那么這個(gè)根下面的內(nèi)容就不會(huì)被暫?;謴?fù)運(yùn)行了,而移動(dòng)過(guò)程中,通過(guò)讀屏障來(lái)看這個(gè)內(nèi)存是不是發(fā)生移動(dòng),如果在移動(dòng)稍微停一下,移動(dòng)過(guò)去后再使用,hotspot還沒(méi)這么厲害,暫停時(shí)間還是挺長(zhǎng)的,只是相對(duì)其他的GC策略在面對(duì)大內(nèi)存來(lái)講是不錯(cuò)的選擇。
下面看一些CMS的策略(并發(fā)GC總時(shí)間會(huì)比常規(guī)的并行GC長(zhǎng),因?yàn)樗窃谶\(yùn)行時(shí)去做GC,很多資源征用都會(huì)影響其GC的效率,而總體的暫停時(shí)間會(huì)短暫很多很多,其并行線程數(shù)默認(rèn)為:(上面設(shè)置的并行線程數(shù) + 3)/ 4
付:CMS是目前Hotspot管理大內(nèi)存最好的JVM,如果是常規(guī)的JVM,最佳選擇為ParallelOldGC,如果必須要以響應(yīng)時(shí)間為準(zhǔn),則選擇CMS,不過(guò)CMS有兩個(gè)隱藏的隱患:
1、CMS GC雖然是并發(fā)且并行運(yùn)行的GC,但是初始化的時(shí)候如果采用默認(rèn)值92%(JVM 1.5的白皮書(shū)上描述為68%其實(shí)是錯(cuò)誤的,1.6是正確的),就很容易出現(xiàn)問(wèn)題,因?yàn)?strong>CMS GC僅僅針對(duì)Old區(qū)域,Yong區(qū)域使用ParNew算法,也就是Old的CMS回收和Yong的回收可以同時(shí)進(jìn)行,也就是回收過(guò)程中Yong有可能會(huì)晉升對(duì)象Old,并且業(yè)務(wù)也可以同時(shí)運(yùn)行,所以92%基本開(kāi)始啟動(dòng)CMS GC很有可能old的內(nèi)存就不夠用了,當(dāng)內(nèi)存不夠用的時(shí)候,就啟動(dòng)Full GC,并且這個(gè)Full GC是串行的,所以如果弄的不好,CMS會(huì)比并行GC更加慢,為什么要啟用串行是因?yàn)镃MS GC、并行GC、串行GC的繼承關(guān)系決定的,簡(jiǎn)單說(shuō)就是它沒(méi)辦法去調(diào)用并行GC的代碼,細(xì)節(jié)說(shuō)后續(xù)有文章來(lái)細(xì)節(jié)說(shuō)明),建議這個(gè)值設(shè)置為70%左右吧,不過(guò)具體時(shí)間還是自己決定。
2、CMS GC另一個(gè)大的隱患,其實(shí)不看也差不多應(yīng)該清楚,看名字就知道,就是不會(huì)做Compact操作,它最惡心的地方也在這里,所以上面才說(shuō)一般的應(yīng)用都不使用它,它只有內(nèi)存垃圾非常多,多得無(wú)法分配晉升的空間的時(shí)候才會(huì)出現(xiàn)一次compact,但是這個(gè)是Full GC,也就是上面的串行,很恐怖的,所以內(nèi)存不是很大的,不要考慮使用它,而且它的算法十分復(fù)雜。
還有一些小的隱患是:和應(yīng)用一起征用CPU(不過(guò)這個(gè)不是大問(wèn)題,增加CPU即可)、整個(gè)運(yùn)行過(guò)程中時(shí)間比并行GC長(zhǎng)(這個(gè)也不是大問(wèn)題,因?yàn)槲覀兏雨P(guān)心暫停時(shí)間而不是運(yùn)行時(shí)間,因?yàn)闀和?huì)影響非常多的業(yè)務(wù))。
啟動(dòng)CMS為全局GC方法(注意這個(gè)參數(shù)也不能上面的并行GC進(jìn)行混淆,Yong默認(rèn)是并行的,上面已經(jīng)說(shuō)過(guò)
-XX:+UseConcMarkSweepGC
在并發(fā)GC下啟動(dòng)增量模式,只能在CMS GC下這個(gè)參數(shù)才有效。
-XX:+CMSIncrementalMode
啟動(dòng)自動(dòng)調(diào)節(jié)duty cycle,即在CMS GC中發(fā)生的時(shí)間比率設(shè)置,也就是說(shuō)這段時(shí)間內(nèi)最大允許發(fā)生多長(zhǎng)時(shí)間的GC工作是可以調(diào)整的。
-XX:+CMSIncrementalPacing
在上面這個(gè)參數(shù)設(shè)定后可以分別設(shè)置以下兩個(gè)參數(shù)(參數(shù)設(shè)置的比率,范圍為0-100):
-XX:CMSIncrementalDutyCycleMin=0
-XX:CMSIncrementalDutyCycle=10
增量GC上還有一個(gè)保護(hù)因子(CMSIncrementalSafetyFactor),不太常用;CMSIncrementalOffset提供增量GC連續(xù)時(shí)間比率的設(shè)置;CMSExpAvgFactor為增量并發(fā)的GC增加權(quán)重計(jì)算。
-XX:CMSIncrementalSafetyFactor=
-XX:CMSIncrementalOffset=
-XX:CMSExpAvgFactor=
是否啟動(dòng)并行CMS GC(默認(rèn)也是開(kāi)啟的)
-XX:+CMSParallelRemarkEnabled
要單獨(dú)對(duì)CMS GC設(shè)置并行線程數(shù)就設(shè)置(默認(rèn)也不需要設(shè)置):
-XX:ParallelCMSThreads
對(duì)PernGen進(jìn)行垃圾回收:
JDK 1.5在CMS GC基礎(chǔ)上需要設(shè)置參數(shù)(也就是前提是CMS GC才有):
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
1.6以后的版本無(wú)需設(shè)置:-XX:+CMSPermGenSweepingEnabled,注意,其實(shí)一直以來(lái)Full GC都會(huì)觸發(fā)對(duì)Perm的回收過(guò)程,CMS GC需要有一些特殊照顧,雖然VM會(huì)對(duì)這塊區(qū)域回收,但是Perm回收的條件幾乎不太可能實(shí)現(xiàn),首先需要這個(gè)類的classloader必須死掉,才可以將該classloader下所有的class干掉,也就是要么全部死掉,要么全部活著;另外,這個(gè)classloader下的class沒(méi)有任何object在使用,這個(gè)也太苛刻了吧,因?yàn)槌R?guī)的對(duì)象申請(qǐng)都是通過(guò)系統(tǒng)默認(rèn)的,應(yīng)用服務(wù)器也有自己默認(rèn)的classloader,要讓它死掉可能性不大,如果這都死掉了,系統(tǒng)也應(yīng)該快掛了。
CMS GC因?yàn)槭窃诔绦蜻\(yùn)行時(shí)進(jìn)行GC,不會(huì)暫停,所以不能等到不夠用的時(shí)候才去開(kāi)啟GC,官方說(shuō)法是他們的默認(rèn)值是68%,但是可惜的是文檔寫(xiě)錯(cuò)了,經(jīng)過(guò)很多測(cè)試和源碼驗(yàn)證這個(gè)參數(shù)應(yīng)該是在92%的時(shí)候被啟動(dòng),雖然還有8%的空間,但是還是很可憐了,當(dāng)CMS發(fā)現(xiàn)內(nèi)存實(shí)在不夠的時(shí)候又回到常規(guī)的并行GC,所以很多人在沒(méi)有設(shè)置這個(gè)參數(shù)的時(shí)候發(fā)現(xiàn)CMS GC并沒(méi)有神馬優(yōu)勢(shì)嘛,和并行GC一個(gè)鳥(niǎo)樣子甚至于更加慢,所以這個(gè)時(shí)候需要設(shè)置參數(shù)(這個(gè)參數(shù)在上面已經(jīng)說(shuō)過(guò),啟動(dòng)CMS一定要設(shè)置這個(gè)參數(shù)):
-XX:CMSInitiatingOccupancyFraction=70
這樣保證Old的內(nèi)存在使用到70%的時(shí)候,就開(kāi)始啟動(dòng)CMS了;如果你真的想看看默認(rèn)值,那么就使用參數(shù):-XX:+PrintCMSInitiationStatistics 這個(gè)變量只有JDK 1.6可以使用 1.5不可以,查看實(shí)際值-XX:+PrintCMSStatistics;另外,還可以設(shè)置參數(shù)-XX:CMSInitiatingPermOccupancyFraction來(lái)設(shè)置Perm空間達(dá)到多少時(shí)啟動(dòng)CMS GC,不過(guò)意義不大。
JDK 1.6以后有些時(shí)候啟動(dòng)CMS GC是根據(jù)計(jì)算代價(jià)進(jìn)行啟動(dòng),也就是不一定按照你指定的參數(shù)來(lái)設(shè)置的,如果你不想讓它按照所謂的成本來(lái)計(jì)算GC的話,那么你就使用一個(gè)參數(shù):-XX:+UseCMSInitiatingOccupancyOnly,默認(rèn)是false,它就只會(huì)按照你設(shè)置的比率來(lái)啟動(dòng)CMS GC了。如果你的程序中有System.gc以及設(shè)置了ExplicitGCInvokesConcurrent在jdk 1.6中,這種情況使用NIO是有可能產(chǎn)生問(wèn)題的。
啟動(dòng)CMS GC的compation操作,也就是發(fā)生多少次后做一次全局的compaction:
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction:發(fā)生多少次CMS Full GC,這個(gè)參數(shù)最好不要設(shè)置,因?yàn)橐鯿ompaction的話,也就是真正的Full GC是串行的,非常慢,讓它自己去決定什么時(shí)候需要做compaction。
-XX:CMSMaxAbortablePrecleanTime=5000 設(shè)置preclean步驟的超時(shí)時(shí)間,單位為毫秒,preclean為cms gc其中一個(gè)步驟,關(guān)于cms gc步驟比較多,本文就不細(xì)節(jié)探討了。
并行GC在mark階段,可能會(huì)同時(shí)發(fā)生minor GC,old區(qū)域也可能發(fā)生改變,于是并發(fā)GC會(huì)對(duì)發(fā)生了改變的內(nèi)容進(jìn)行remark操作,這個(gè)觸發(fā)的條件是:
-XX:CMSScheduleRemarkEdenSizeThreshold
-XX:CMSScheduleRemarkEdenPenetration
即Eden區(qū)域多大的時(shí)候開(kāi)始觸發(fā),和eden使用量超過(guò)百分比多少的時(shí)候觸發(fā),前者默認(rèn)是2M,后者默認(rèn)是50%。
但是如果長(zhǎng)期不做remark導(dǎo)致old做不了,可以設(shè)置超時(shí),這個(gè)超時(shí)默認(rèn)是5秒,可以通過(guò)參數(shù):
-XX:CMSMaxAbortablePrecleanTime
-XX:+ExplicitGCInvokesConcurrent 在顯示發(fā)生GC的時(shí)候,允許進(jìn)行并行GC。
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses 幾乎和上面一樣,只不過(guò)多一個(gè)對(duì)Perm區(qū)域的回收而已。
補(bǔ)充:
其實(shí)JVM還有很多的版本,很多的廠商,與其優(yōu)化的原則,隨便舉兩個(gè)例子hotspot在GC中做的一些優(yōu)化(這里不說(shuō)代碼的編譯時(shí)優(yōu)化或運(yùn)行時(shí)優(yōu)化):
Eden申請(qǐng)的空間對(duì)象由Old區(qū)域的某個(gè)對(duì)象的一個(gè)屬性指向(也就是Old區(qū)域的這個(gè)空間不回收,Eden這塊就沒(méi)有必要考慮回收),所以Hotspot在CPU寫(xiě)上面,做了一個(gè)屏障,當(dāng)發(fā)生賦值語(yǔ)句的時(shí)候(對(duì)內(nèi)存來(lái)講賦值就是一種寫(xiě)操作),如果發(fā)現(xiàn)是一個(gè)新的對(duì)象由Old指向Eden,那么就會(huì)將這個(gè)對(duì)象記錄在一個(gè)卡片機(jī)里面,這個(gè)卡片機(jī)是有很多512字節(jié)的卡片組成,當(dāng)在YGC過(guò)程中,就基本不會(huì)去移動(dòng)或者管理這塊對(duì)象(付:這種卡片機(jī)會(huì)在CMS GC的算法中使用,不過(guò)和這個(gè)卡片不是放在同一個(gè)地方的,也是CMS GC的關(guān)鍵,對(duì)于CMS GC的算法細(xì)節(jié)描述,后續(xù)文章我們單獨(dú)說(shuō)明)。
Old區(qū)域?qū)τ谝恍┍容^大的對(duì)象,JVM就不會(huì)去管理個(gè)對(duì)象,也就是compact過(guò)程中不會(huì)去移動(dòng)這塊對(duì)象的區(qū)域等等吧。
以上大部分參數(shù)為hotspot的自帶關(guān)于性能的參數(shù),參考版本為JDK 1.5和1.6的版本,很多為個(gè)人經(jīng)驗(yàn)說(shuō)明,不足以說(shuō)明所有問(wèn)題,如果有問(wèn)題,歡迎探討;另外,JDK的參數(shù)是不是就只有這些呢,肯定并不是,我知道的也不止這些,但是有些覺(jué)得沒(méi)必要說(shuō)出來(lái)的參數(shù)和一些數(shù)學(xué)運(yùn)算的參數(shù)我就不想給出來(lái)了,比如像禁用掉GC的參數(shù)有神馬意義,我們的服務(wù)器要是把這個(gè)禁用掉干個(gè)屁啊,呵呵,做測(cè)試還可以用這玩玩,讓它不做GC直接溢出;還有一些什么計(jì)算因子啥的,還有很多復(fù)雜的數(shù)學(xué)運(yùn)算規(guī)則,要是把這個(gè)配置明白了,就太那個(gè)了,而且一般情況下也沒(méi)那個(gè)必要,JDK到現(xiàn)在的配置參數(shù)多達(dá)上500個(gè)以上,要知道完的話慢慢看吧,不過(guò)意義不大,而且要知道默認(rèn)值最靠譜的是看源碼而不是看文檔,官方文檔也只能保證絕大部是正確的,不能保證所有的是正確的。
本文最后追加在jdk 1.6u 24后通過(guò)上面說(shuō)明的-XX:+PrintFlagsFinal輸出的參數(shù)以及默認(rèn)值(還是那句話,在不同的平臺(tái)上是不一樣的),輸出的參數(shù)如下,可以看看JVM的參數(shù)是相當(dāng)?shù)亩?,參?shù)如此之多,你只需要掌握關(guān)鍵即可,參數(shù)還有很多有沖突的,不要糾結(jié)于每一個(gè)參數(shù)的細(xì)節(jié):
$java -XX:+PrintFlagsFinal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
|
uintx AdaptivePermSizeWeight = 20 {product} uintx AdaptiveSizeDecrementScaleFactor = 4 {product} uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product} uintx AdaptiveSizePausePolicy = 0 {product} uintx AdaptiveSizePolicyCollectionCostMargin = 50 {product} uintx AdaptiveSizePolicyInitializingSteps = 20 {product} uintx AdaptiveSizePolicyOutputInterval = 0 {product} uintx AdaptiveSizePolicyWeight = 10 {product} uintx AdaptiveSizeThroughPutPolicy = 0 {product} uintx AdaptiveTimeWeight = 25 {product} bool AdjustConcurrency = false {product} bool AggressiveOpts = false {product} intx AliasLevel = 3 {product} intx AllocatePrefetchDistance = - 1 {product} intx AllocatePrefetchInstr = 0 {product} intx AllocatePrefetchLines = 1 {product} intx AllocatePrefetchStepSize = 16 {product} intx AllocatePrefetchStyle = 1 {product} bool AllowJNIEnvProxy = false {product} bool AllowParallelDefineClass = false {product} bool AllowUserSignalHandlers = false {product} bool AlwaysActAsServerClassMachine = false {product} bool AlwaysCompileLoopMethods = false {product} intx AlwaysInflate = 0 {product} bool AlwaysLockClassLoader = false {product} bool AlwaysPreTouch = false {product} bool AlwaysRestoreFPU = false {product} bool AlwaysTenure = false {product} bool AnonymousClasses = false {product} bool AssertOnSuspendWaitFailure = false {product} intx Atomics = 0 {product} uintx AutoGCSelectPauseMillis = 5000 {product} intx BCEATraceLevel = 0 {product} intx BackEdgeThreshold = 100000 {pd product} bool BackgroundCompilation = true {pd product} uintx BaseFootPrintEstimate = 268435456 {product} intx BiasedLockingBulkRebiasThreshold = 20 {product} intx BiasedLockingBulkRevokeThreshold = 40 {product} intx BiasedLockingDecayTime = 25000 {product} intx BiasedLockingStartupDelay = 4000 {product} bool BindGCTaskThreadsToCPUs = false {product} bool BlockOffsetArrayUseUnallocatedBlock = false {product} bool BytecodeVerificationLocal = false {product} bool BytecodeVerificationRemote = true {product} intx CICompilerCount = 1 {product} bool CICompilerCountPerCPU = false {product} bool CITime = false {product} bool CMSAbortSemantics = false {product} uintx CMSAbortablePrecleanMinWorkPerIteration = 100 {product} intx CMSAbortablePrecleanWaitMillis = 100 {product} uintx CMSBitMapYieldQuantum = 10485760 {product} uintx CMSBootstrapOccupancy = 50 {product} bool CMSClassUnloadingEnabled = false {product} uintx CMSClassUnloadingMaxInterval = 0 {product} bool CMSCleanOnEnter = true {product} bool CMSCompactWhenClearAllSoftRefs = true {product} uintx CMSConcMarkMultiple = 32 {product} bool CMSConcurrentMTEnabled = true {product} uintx CMSCoordinatorYieldSleepCount = 10 {product} bool CMSDumpAtPromotionFailure = false {product} uintx CMSExpAvgFactor = 50 {product} bool CMSExtrapolateSweep = false {product} uintx CMSFullGCsBeforeCompaction = 0 {product} uintx CMSIncrementalDutyCycle = 10 {product} uintx CMSIncrementalDutyCycleMin = 0 {product} bool CMSIncrementalMode = false {product} uintx CMSIncrementalOffset = 0 {product} bool CMSIncrementalPacing = true {product} uintx CMSIncrementalSafetyFactor = 10 {product} uintx CMSIndexedFreeListReplenish = 4 {product} intx CMSInitiatingOccupancyFraction = - 1 {product} intx CMSInitiatingPermOccupancyFraction = - 1 {product} intx CMSIsTooFullPercentage = 98 {product} double CMSLargeCoalSurplusPercent = {product} double CMSLargeSplitSurplusPercent = {product} bool CMSLoopWarn = false {product} uintx CMSMaxAbortablePrecleanLoops = 0 {product} intx CMSMaxAbortablePrecleanTime = 5000 {product} uintx CMSOldPLABMax = 1024 {product} uintx CMSOldPLABMin = 16 {product} uintx CMSOldPLABNumRefills = 4 {product} uintx CMSOldPLABReactivityCeiling = 10 {product} uintx CMSOldPLABReactivityFactor = 2 {product} bool CMSOldPLABResizeQuicker = false {product} uintx CMSOldPLABToleranceFactor = 4 {product} bool CMSPLABRecordAlways = true {product} uintx CMSParPromoteBlocksToClaim = 16 {product} bool CMSParallelRemarkEnabled = true {product} bool CMSParallelSurvivorRemarkEnabled = true {product} bool CMSPermGenPrecleaningEnabled = true {product} uintx CMSPrecleanDenominator = 3 {product} uintx CMSPrecleanIter = 3 {product} uintx CMSPrecleanNumerator = 2 {product} bool CMSPrecleanRefLists1 = true {product} bool CMSPrecleanRefLists2 = false {product} bool CMSPrecleanSurvivors1 = false {product} bool CMSPrecleanSurvivors2 = true {product} uintx CMSPrecleanThreshold = 1000 {product} bool CMSPrecleaningEnabled = true {product} bool CMSPrintChunksInDump = false {product} bool CMSPrintObjectsInDump = false {product} uintx CMSRemarkVerifyVariant = 1 {product} bool CMSReplenishIntermediate = true {product} uintx CMSRescanMultiple = 32 {product} uintx CMSRevisitStackSize = 1048576 {product} uintx CMSSamplingGrain = 16384 {product} bool CMSScavengeBeforeRemark = false {product} uintx CMSScheduleRemarkEdenPenetration = 50 {product} uintx CMSScheduleRemarkEdenSizeThreshold = 2097152 {product} uintx CMSScheduleRemarkSamplingRatio = 5 {product} double CMSSmallCoalSurplusPercent = {product} double CMSSmallSplitSurplusPercent = {product} bool CMSSplitIndexedFreeListBlocks = true {product} intx CMSTriggerPermRatio = 80 {product} intx CMSTriggerRatio = 80 {product} bool CMSUseOldDefaults = false {product} intx CMSWaitDuration = 2000 {product} uintx CMSWorkQueueDrainThreshold = 10 {product} bool CMSYield = true {product} uintx CMSYieldSleepCount = 0 {product} intx CMSYoungGenPerWorker = 16777216 {product} uintx CMS_FLSPadding = 1 {product} uintx CMS_FLSWeight = 75 {product} uintx CMS_SweepPadding = 1 {product} uintx CMS_SweepTimerThresholdMillis = 10 {product} uintx CMS_SweepWeight = 75 {product} bool CheckJNICalls = false {product} bool ClassUnloading = true {product} intx ClearFPUAtPark = 0 {product} bool ClipInlining = true {product} uintx CodeCacheExpansionSize = 32768 {pd product} uintx CodeCacheFlushingMinimumFreeSpace = 1536000 {product} uintx CodeCacheMinimumFreeSpace = 512000 {product} bool CollectGen0First = false {product} bool CompactFields = true {product} intx CompilationPolicyChoice = 0 {product} intx CompilationRepeat = 0 {C1 product} ccstrlist CompileCommand = {product} ccstr CompileCommandFile = {product} ccstrlist CompileOnly = {product} intx CompileThreshold = 1500 {pd product} bool CompilerThreadHintNoPreempt = true {product} intx CompilerThreadPriority = - 1 {product} intx CompilerThreadStackSize = 0 {pd product} uintx ConcGCThreads = 0 {product} bool ConvertSleepToYield = true {pd product} bool ConvertYieldToSleep = false {product} bool DTraceAllocProbes = false {product} bool DTraceMethodProbes = false {product} bool DTraceMonitorProbes = false {product} uintx DefaultMaxRAMFraction = 4 {product} intx DefaultThreadPriority = - 1 {product} intx DeferPollingPageLoopCount = - 1 {product} intx DeferThrSuspendLoopCount = 4000 {product} bool DeoptimizeRandom = false {product} bool DisableAttachMechanism = false {product} bool DisableExplicitGC = false {product} bool DisplayVMOutputToStderr = false {product} bool DisplayVMOutputToStdout = false {product} bool DontCompileHugeMethods = true {product} bool DontYieldALot = false {pd product} bool DumpSharedSpaces = false {product} bool EagerXrunInit = false {product} intx EmitSync = 0 {product} uintx ErgoHeapSizeLimit = 0 {product} ccstr ErrorFile = {product} bool EstimateArgEscape = true {product} intx EventLogLength = 2000 {product} bool ExplicitGCInvokesConcurrent = false {product} bool ExplicitGCInvokesConcurrentAndUnloadsClasses = false {produ bool ExtendedDTraceProbes = false {product} bool FLSAlwaysCoalesceLarge = false {product} uintx FLSCoalescePolicy = 2 {product} double FLSLargestBlockCoalesceProximity = {product} bool FailOverToOldVerifier = true {product} bool FastTLABRefill = true {product} intx FenceInstruction = 0 {product} intx FieldsAllocationStyle = 1 {product} bool FilterSpuriousWakeups = true {product} bool ForceFullGCJVMTIEpilogues = false {product} bool ForceNUMA = false {product} bool ForceSharedSpaces = false {product} bool ForceTimeHighResolution = false {product} intx FreqInlineSize = 325 {pd product} intx G1ConcRefinementGreenZone = 0 {product} intx G1ConcRefinementRedZone = 0 {product} intx G1ConcRefinementServiceIntervalMillis = 300 {product} uintx G1ConcRefinementThreads = 0 {product} intx G1ConcRefinementThresholdStep = 0 {product} intx G1ConcRefinementYellowZone = 0 {product} intx G1ConfidencePercent = 50 {product} uintx G1HeapRegionSize = 0 {product} intx G1MarkRegionStackSize = 1048576 {product} intx G1RSetRegionEntries = 0 {product} uintx G1RSetScanBlockSize = 64 {product} intx G1RSetSparseRegionEntries = 0 {product} intx G1RSetUpdatingPauseTimePercent = 10 {product} intx G1ReservePercent = 10 {product} intx G1SATBBufferSize = 1024 {product} intx G1UpdateBufferSize = 256 {product} bool G1UseAdaptiveConcRefinement = true {product} bool G1UseFixedWindowMMUTracker = false {product} uintx GCDrainStackTargetSize = 64 {product} uintx GCHeapFreeLimit = 2 {product} bool GCLockerInvokesConcurrent = false {product} bool GCOverheadReporting = false {product} intx GCOverheadReportingPeriodMS = 100 {product} intx GCPauseIntervalMillis = 500 {product} uintx GCTaskTimeStampEntries = 200 {product} uintx GCTimeLimit = 98 {product} uintx GCTimeRatio = 99 {product} ccstr HPILibPath = {product} bool HandlePromotionFailure = true {product} uintx HeapBaseMinAddress = 2147483648 {pd product} bool HeapDumpAfterFullGC = false {manageable} bool HeapDumpBeforeFullGC = false {manageable} bool HeapDumpOnOutOfMemoryError = false {manageable} ccstr HeapDumpPath = {manageable} uintx HeapFirstMaximumCompactionCount = 3 {product} uintx HeapMaximumCompactionInterval = 20 {product} bool IgnoreUnrecognizedVMOptions = false {product} uintx InitialCodeCacheSize = 163840 {pd product} uintx InitialHeapSize := 16777216 {product} uintx InitialRAMFraction = 64 {product} uintx InitialSurvivorRatio = 8 {product} intx InitialTenuringThreshold = 7 {product} uintx InitiatingHeapOccupancyPercent = 45 {product} bool Inline = true {product} intx InlineSmallCode = 1000 {pd product} intx InterpreterProfilePercentage = 33 {product} bool JNIDetachReleasesMonitors = true {product} bool JavaMonitorsInStackTrace = true {product} intx JavaPriority10_To_OSPriority = - 1 {product} intx JavaPriority1_To_OSPriority = - 1 {product} intx JavaPriority2_To_OSPriority = - 1 {product} intx JavaPriority3_To_OSPriority = - 1 {product} intx JavaPriority4_To_OSPriority = - 1 {product} intx JavaPriority5_To_OSPriority = - 1 {product} intx JavaPriority6_To_OSPriority = - 1 {product} intx JavaPriority7_To_OSPriority = - 1 {product} intx JavaPriority8_To_OSPriority = - 1 {product} intx JavaPriority9_To_OSPriority = - 1 {product} bool LIRFillDelaySlots = false {C1 pd product} uintx LargePageHeapSizeThreshold = 134217728 {product} uintx LargePageSizeInBytes = 0 {product} bool LazyBootClassLoader = true {product} bool ManagementServer = false {product} uintx MarkStackSize = 32768 {product} uintx MarkStackSizeMax = 4194304 {product} intx MarkSweepAlwaysCompactCount = 4 {product} uintx MarkSweepDeadRatio = 5 {product} intx MaxBCEAEstimateLevel = 5 {product} intx MaxBCEAEstimateSize = 150 {product} intx MaxDirectMemorySize = - 1 {product} bool MaxFDLimit = true {product} uintx MaxGCMinorPauseMillis = 4294967295 {product} uintx MaxGCPauseMillis = 4294967295 {product} uintx MaxHeapFreeRatio = 70 {product} uintx MaxHeapSize := 268435456 {product} intx MaxInlineLevel = 9 {product} intx MaxInlineSize = 35 {product} intx MaxJavaStackTraceDepth = 1024 {product} uintx MaxLiveObjectEvacuationRatio = 100 {product} uintx MaxNewSize = 4294967295 {product} uintx MaxPermHeapExpansion = 4194304 {product} uintx MaxPermSize = 67108864 {pd product} uint64_t MaxRAM = 1073741824 {pd product} uintx MaxRAMFraction = 4 {product} intx MaxRecursiveInlineLevel = 1 {product} intx MaxTenuringThreshold = 15 {product} intx MaxTrivialSize = 6 {product} bool MethodFlushing = true {product} intx MinCodeCacheFlushingInterval = 30 {product} uintx MinHeapDeltaBytes = 131072 {product} uintx MinHeapFreeRatio = 40 {product} intx MinInliningThreshold = 250 {product} uintx MinPermHeapExpansion = 262144 {product} uintx MinRAMFraction = 2 {product} uintx MinSurvivorRatio = 3 {product} uintx MinTLABSize = 2048 {product} intx MonitorBound = 0 {product} bool MonitorInUseLists = false {product} bool MustCallLoadClassInternal = false {product} intx NUMAChunkResizeWeight = 20 {product} intx NUMAPageScanRate = 256 {product} intx NUMASpaceResizeRate = 1073741824 {product} bool NUMAStats = false {product} intx NativeMonitorFlags = 0 {product} intx NativeMonitorSpinLimit = 20 {product} intx NativeMonitorTimeout = - 1 {product} bool NeedsDeoptSuspend = false {pd product} bool NeverActAsServerClassMachine = true {pd product} bool NeverTenure = false {product} intx NewRatio = 2 {product} uintx NewSize = 1048576 {product} uintx NewSizeThreadIncrease = 4096 {pd product} intx NmethodSweepFraction = 4 {product} uintx OldPLABSize = 1024 {product} uintx OldPLABWeight = 50 {product} uintx OldSize = 4194304 {product} bool OmitStackTraceInFastThrow = true {product} ccstrlist OnError = {product} ccstrlist OnOutOfMemoryError = {product} intx OnStackReplacePercentage = 933 {pd product} uintx PLABWeight = 75 {product} bool PSChunkLargeArrays = true {product} intx ParGCArrayScanChunk = 50 {product} uintx ParGCDesiredObjsFromOverflowList = 20 {product} bool ParGCTrimOverflow = true {product} bool ParGCUseLocalOverflow = false {product} intx ParallelGCBufferWastePct = 10 {product} bool ParallelGCRetainPLAB = true {product} uintx ParallelGCThreads = 0 {product} bool ParallelGCVerbose = false {product} uintx ParallelOldDeadWoodLimiterMean = 50 {product} uintx ParallelOldDeadWoodLimiterStdDev = 80 {product} bool ParallelRefProcBalancingEnabled = true {product} bool ParallelRefProcEnabled = false {product} uintx PausePadding = 1 {product} intx PerBytecodeRecompilationCutoff = 200 {product} intx PerBytecodeTrapLimit = 4 {product} intx PerMethodRecompilationCutoff = 400 {product} intx PerMethodTrapLimit = 100 {product} bool PerfAllowAtExitRegistration = false {product} bool PerfBypassFileSystemCheck = false {product} intx PerfDataMemorySize = 32768 {product} intx PerfDataSamplingInterval = 50 {product} ccstr PerfDataSaveFile = {product} bool PerfDataSaveToFile = false {product} bool PerfDisableSharedMem = false {product} intx PerfMaxStringConstLength = 1024 {product} uintx PermGenPadding = 3 {product} uintx PermMarkSweepDeadRatio = 20 {product} uintx PermSize = 12582912 {pd product} bool PostSpinYield = true {product} intx PreBlockSpin = 10 {product} intx PreInflateSpin = 10 {pd product} bool PreSpinYield = false {product} bool PreferInterpreterNativeStubs = false {pd product} intx PrefetchCopyIntervalInBytes = - 1 {product} intx PrefetchFieldsAhead = - 1 {product} intx PrefetchScanIntervalInBytes = - 1 {product} bool PreserveAllAnnotations = false {product} uintx PreserveMarkStackSize = 1024 {product} uintx PretenureSizeThreshold = 0 {product} bool PrintAdaptiveSizePolicy = false {product} bool PrintCMSInitiationStatistics = false {product} intx PrintCMSStatistics = 0 {product} bool PrintClassHistogram = false {manageable} bool PrintClassHistogramAfterFullGC = false {manageable} bool PrintClassHistogramBeforeFullGC = false {manageable} bool PrintCommandLineFlags = false {product} bool PrintCompilation = false {product} bool PrintConcurrentLocks = false {manageable} intx PrintFLSCensus = 0 {product} intx PrintFLSStatistics = 0 {product} bool PrintFlagsFinal := true {product} bool PrintFlagsInitial = false {product} bool PrintGC = false {manageable} bool PrintGCApplicationConcurrentTime = false {product} bool PrintGCApplicationStoppedTime = false {product} bool PrintGCDateStamps = false {manageable} bool PrintGCDetails = false {manageable} bool PrintGCTaskTimeStamps = false {product} bool PrintGCTimeStamps = false {manageable} bool PrintHeapAtGC = false {product rw} bool PrintHeapAtGCExtended = false {product rw} bool PrintHeapAtSIGBREAK = true {product} bool PrintJNIGCStalls = false {product} bool PrintJNIResolving = false {product} bool PrintOldPLAB = false {product} bool PrintPLAB = false {product} bool PrintParallelOldGCPhaseTimes = false {product} bool PrintPromotionFailure = false {product} bool PrintReferenceGC = false {product} bool PrintRevisitStats = false {product} bool PrintSafepointStatistics = false {product} intx PrintSafepointStatisticsCount = 300 {product} intx PrintSafepointStatisticsTimeout = - 1 {product} bool PrintSharedSpaces = false {product} bool PrintTLAB = false {product} bool PrintTenuringDistribution = false {product} bool PrintVMOptions = false {product} bool PrintVMQWaitTime = false {product} uintx ProcessDistributionStride = 4 {product} bool ProfileInterpreter = false {pd product} bool ProfileIntervals = false {product} intx ProfileIntervalsTicks = 100 {product} intx ProfileMaturityPercentage = 20 {product} bool ProfileVM = false {product} bool ProfilerPrintByteCodeStatistics = false {product} bool ProfilerRecordPC = false {product} uintx PromotedPadding = 3 {product} intx QueuedAllocationWarningCount = 0 {product} bool RangeCheckElimination = true {product} intx ReadPrefetchInstr = 0 {product} intx ReadSpinIterations = 100 {product} bool ReduceSignalUsage = false {product} intx RefDiscoveryPolicy = 0 {product} bool ReflectionWrapResolutionErrors = true {product} bool RegisterFinalizersAtInit = true {product} bool RelaxAccessControlCheck = false {product} bool RequireSharedSpaces = false {product} uintx ReservedCodeCacheSize = 33554432 {pd product} bool ResizeOldPLAB = true {product} bool ResizePLAB = true {product} bool ResizeTLAB = true {pd product} bool RestoreMXCSROnJNICalls = false {product} bool RewriteBytecodes = false {pd product} bool RewriteFrequentPairs = false {pd product} intx SafepointPollOffset = 256 {C1 pd product} intx SafepointSpinBeforeYield = 2000 {product} bool SafepointTimeout = false {product} intx SafepointTimeoutDelay = 10000 {product} bool ScavengeBeforeFullGC = true {product} intx SelfDestructTimer = 0 {product} uintx SharedDummyBlockSize = 536870912 {product} uintx SharedMiscCodeSize = 4194304 {product} uintx SharedMiscDataSize = 4194304 {product} uintx SharedReadOnlySize = 10485760 {product} uintx SharedReadWriteSize = 12582912 {product} bool ShowMessageBoxOnError = false {product} intx SoftRefLRUPolicyMSPerMB = 1000 {product} bool SplitIfBlocks = true {product} intx StackRedPages = 1 {pd product} intx StackShadowPages = 3 {pd product} bool StackTraceInThrowable = true {product} intx StackYellowPages = 2 {pd product} bool StartAttachListener = false {product} intx StarvationMonitorInterval = 200 {product} bool StressLdcRewrite = false {product} bool StressTieredRuntime = false {product} bool SuppressFatalErrorMessage = false {product} uintx SurvivorPadding = 3 {product} intx SurvivorRatio = 8 {product} intx SuspendRetryCount = 50 {product} intx SuspendRetryDelay = 5 {product} intx SyncFlags = 0 {product} ccstr SyncKnobs = {product} intx SyncVerbose = 0 {product} uintx TLABAllocationWeight = 35 {product} uintx TLABRefillWasteFraction = 64 {product} uintx TLABSize = 0 {product} bool TLABStats = true {product} uintx TLABWasteIncrement = 4 {product} uintx TLABWasteTargetPercent = 1 {product} bool TaggedStackInterpreter = false {product} intx TargetPLABWastePct = 10 {product} intx TargetSurvivorRatio = 50 {product} uintx TenuredGenerationSizeIncrement = 20 {product} uintx TenuredGenerationSizeSupplement = 80 {product} uintx TenuredGenerationSizeSupplementDecay = 2 {product} intx ThreadPriorityPolicy = 0 {product} bool ThreadPriorityVerbose = false {product} uintx ThreadSafetyMargin = 52428800 {product} intx ThreadStackSize = 0 {pd product} uintx ThresholdTolerance = 10 {product} intx Tier1BytecodeLimit = 10 {product} bool Tier1OptimizeVirtualCallProfiling = true {C1 product} bool Tier1ProfileBranches = true {C1 product} bool Tier1ProfileCalls = true {C1 product} bool Tier1ProfileCheckcasts = true {C1 product} bool Tier1ProfileInlinedCalls = true {C1 product} bool Tier1ProfileVirtualCalls = true {C1 product} bool Tier1UpdateMethodData = false {product} intx Tier2BackEdgeThreshold = 100000 {pd product} intx Tier2CompileThreshold = 1500 {pd product} intx Tier3BackEdgeThreshold = 100000 {pd product} intx Tier3CompileThreshold = 2500 {pd product} intx Tier4BackEdgeThreshold = 100000 {pd product} intx Tier4CompileThreshold = 4500 {pd product} bool TieredCompilation = false {pd product} bool TimeLinearScan = false {C1 product} bool TraceBiasedLocking = false {product} bool TraceClassLoading = false {product rw} bool TraceClassLoadingPreorder = false {product} bool TraceClassResolution = false {product} bool TraceClassUnloading = false {product rw} bool TraceGen0Time = false {product} bool TraceGen1Time = false {product} ccstr TraceJVMTI = {product} bool TraceLoaderConstraints = false {product rw} bool TraceMonitorInflation = false {product} bool TraceParallelOldGCTasks = false {product} intx TraceRedefineClasses = 0 {product} bool TraceSafepointCleanupTime = false {product} bool TraceSuspendWaitFailures = false {product} intx TypeProfileMajorReceiverPercent = 90 {product} intx TypeProfileWidth = 2 {product} intx UnguardOnExecutionViolation = 0 {product} bool Use486InstrsOnly = false {product} bool UseAdaptiveGCBoundary = false {product} bool UseAdaptiveGenerationSizePolicyAtMajorCollection = true {p bool UseAdaptiveGenerationSizePolicyAtMinorCollection = true {p bool UseAdaptiveNUMAChunkSizing = true {product} bool UseAdaptiveSizeDecayMajorGCCost = true {product} bool UseAdaptiveSizePolicy = true {product} bool UseAdaptiveSizePolicyFootprintGoal = true {product} bool UseAdaptiveSizePolicyWithSystemGC = false {product} bool UseAddressNop = false {product} bool UseAltSigs = false {product} bool UseAutoGCSelectPolicy = false {product} bool UseBiasedLocking = true {product} bool UseBoundThreads = true {product} bool UseCMSBestFit = true {product} bool UseCMSCollectionPassing = true {product} bool UseCMSCompactAtFullCollection = true {product} bool UseCMSInitiatingOccupancyOnly = false {product} bool UseCodeCacheFlushing = false {product} bool UseCompiler = true {product} bool UseCompilerSafepoints = true {product} bool UseConcMarkSweepGC = false {product} bool UseCountLeadingZerosInstruction = false {product} bool UseCounterDecay = true {product} bool UseDepthFirstScavengeOrder = true {product} bool UseFastAccessorMethods = true {product} bool UseFastEmptyMethods = true {product} bool UseFastJNIAccessors = true {product} bool UseG1GC = false {product} bool UseGCOverheadLimit = true {product} bool UseGCTaskAffinity = false {product} bool UseHeavyMonitors = false {product} bool UseInlineCaches = true {product} bool UseInterpreter = true {product} bool UseLWPSynchronization = true {product} bool UseLargePages = false {pd product} bool UseLargePagesIndividualAllocation := false {pd product} bool UseLoopCounter = true {product} bool UseMaximumCompactionOnSystemGC = true {product} bool UseMembar = false {product} bool UseNUMA = false {product} bool UseNewFeature1 = false {C1 product} bool UseNewFeature2 = false {C1 product} bool UseNewFeature3 = false {C1 product} bool UseNewFeature4 = false {C1 product} bool UseNewLongLShift = false {product} bool UseNiagaraInstrs = false {product} bool UseOSErrorReporting = false {pd product} bool UseOnStackReplacement = true {pd product} bool UsePSAdaptiveSurvivorSizePolicy = true {product} bool UseParNewGC = false {product} bool UseParallelDensePrefixUpdate = true {product} bool UseParallelGC = false {product} bool UseParallelOldGC = false {product} bool UseParallelOldGCCompacting = true {product} bool UseParallelOldGCDensePrefix = true {product} bool UsePerfData = true {product} bool UsePopCountInstruction = false {product} intx UseSSE = 99 {product} bool UseSSE42Intrinsics = false {product} bool UseSerialGC = false {product} bool UseSharedSpaces = true {product} bool UseSignalChaining = true {product} bool UseSpinning = false {product} bool UseSplitVerifier = true {product} bool UseStoreImmI16 = true {product} bool UseStringCache = false {product} bool UseTLAB = true {pd product} bool UseThreadPriorities = true {pd product} bool UseTypeProfile = true {product} bool UseUTCFileTimestamp = true {product} bool UseUnalignedLoadStores = false {product} bool UseVMInterruptibleIO = true {product} bool UseVectoredExceptions = false {pd product} bool UseXMMForArrayCopy = false {product} bool UseXmmI2D = false {product} bool UseXmmI2F = false {product} bool UseXmmLoadAndClearUpper = true {product} bool UseXmmRegToRegMoveAll = false {product} bool VMThreadHintNoPreempt = false {product} intx VMThreadPriority = - 1 {product} intx VMThreadStackSize = 0 {pd product} intx ValueMapInitialSize = 11 {C1 product} intx ValueMapMaxLoopSize = 8 {C1 product} bool VerifyMergedCPBytecodes = true {product} intx WorkAroundNPTLTimedWaitHang = 1 {product} uintx YoungGenerationSizeIncrement = 20 {product} uintx YoungGenerationSizeSupplement = 80 {product} uintx YoungGenerationSizeSupplementDecay = 8 {product} uintx YoungPLABSize = 4096 {product} bool ZeroTLAB = false {product} intx hashCode = 0 {product} |
以上這篇老生常談JVM的內(nèi)存溢出說(shuō)明及參數(shù)調(diào)整就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。