日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

探秘Java虛擬機(jī) gc的監(jiān)控

系統(tǒng) 2095 0

1、Java虛擬機(jī)運(yùn)行時的數(shù)據(jù)區(qū)

探秘Java虛擬機(jī) gc的監(jiān)控

2、常用的內(nèi)存區(qū)域調(diào)節(jié)參數(shù)

-Xms :初始堆大小,默認(rèn)為物理內(nèi)存的1/64(<1GB);默認(rèn)(MinHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存小于40%時,JVM就會增大堆直到-Xmx的最大限制

-Xmx :最大堆大小,默認(rèn)(MaxHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存大于70%時,JVM會減少堆直到 -Xms的最小限制

-Xmn :新生代的內(nèi)存空間大小, 注意 :此處的大小是(eden+ 2 survivor space)。與jmap -heap中顯示的New gen是不同的。整個堆大小=新生代大小 + 老生代大小 + 永久代大小。?
在保證堆大小不變的情況下,增大新生代后,將會減小老生代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8。

-XX:SurvivorRatio :新生代中Eden區(qū)域與Survivor區(qū)域的容量比值,默認(rèn)值為8。兩個Survivor區(qū)與一個Eden區(qū)的比值為2:8,一個Survivor區(qū)占整個年輕代的1/10。

-Xss :每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。應(yīng)根據(jù)應(yīng)用的線程所需內(nèi)存大小進(jìn)行適當(dāng)調(diào)整。在相同物理內(nèi)存下,減小這個值能生成更多的線程。但是操作系統(tǒng)對一個進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在3000~5000左右。一般小的應(yīng)用, 如果棧不是很深, 應(yīng)該是128k夠用的,大的應(yīng)用建議使用256k。這個選項對性能影響比較大,需要嚴(yán)格的測試。和threadstacksize選項解釋很類似,官方文檔似乎沒有解釋,在論壇中有這樣一句話:"-Xss is translated in a VM flag named ThreadStackSize”一般設(shè)置這個值就可以了。

-XX:PermSize :設(shè)置永久代(perm gen)初始值。默認(rèn)值為物理內(nèi)存的1/64。

-XX:MaxPermSize :設(shè)置持久代最大值。物理內(nèi)存的1/4。

3、內(nèi)存分配方法

1)堆上分配?? 2)棧上分配? 3)堆外分配(DirectByteBuffer或直接使用Unsafe.allocateMemory,但不推薦這種方式)

4、監(jiān)控方法

1)系統(tǒng)程序運(yùn)行時可通過jstat –gcutil來查看堆中各個內(nèi)存區(qū)域的變化以及GC的工作狀態(tài);?
2)啟動時可添加-XX:+PrintGCDetails? –Xloggc:&lt;file>輸出到日志文件來查看GC的狀況;?
3)jmap –heap可用于查看各個內(nèi)存空間的大小;

5)斷代法可用GC匯總

探秘Java虛擬機(jī) gc的監(jiān)控

一、新生代可用GC

1)串行GC(Serial Copying):client模式下默認(rèn)GC方式, 也可通過-XX:+UseSerialGC來強(qiáng)制指定 ;默認(rèn)情況下 eden、s0、s1的大小通過-XX:SurvivorRatio來控制,默認(rèn)為8,含義?
為eden:s0的比例,啟動后可通過jmap –heap [pid]來查看。

????? 默認(rèn)情況下,僅在TLAB或eden上分配,只有兩種情況下會在老生代分配:?
????? ?1、需要分配的內(nèi)存大小超過eden space大小;?
???? ? 2、在配置了PretenureSizeThreshold的情況下,對象大小大于此值。 -XX:PretenureSizeThreshold=3M

????? 默認(rèn)情況下,觸發(fā)Minor GC時:?
????? 之前Minor GC晉級到old的平均大小 < 老生代的剩余空間 &lt; eden+from Survivor的使用空間。當(dāng)HandlePromotionFailure為true,則僅觸發(fā)minor gc;如為false,則觸發(fā)full GC。

????? 默認(rèn)情況下,新生代對象晉升到老生代的規(guī)則:

???? ?1、經(jīng)歷多次minor gc仍存活的對象,可通過以下參數(shù)來控制:以MaxTenuringThreshold值為準(zhǔn),默認(rèn)為15。?
??? ? 2、to space放不下的,直接放入老生代;

2)并行GC(ParNew):CMS GC時默認(rèn)采用, 也可采用-XX:+UseParNewGC強(qiáng)制指定 ;垃圾回收的時候采用多線程的方式。

3)并行回收GC(Parallel Scavenge):server模式下默認(rèn)的GC方式, 也可采用-XX:+UseParallelGC強(qiáng)制指定 ;eden、s0、s1的大小可通過-XX:SurvivorRatio來控制,但默認(rèn)情況下?
以-XX:InitialSurivivorRatio為準(zhǔn),此值默認(rèn)為8, 代表的為新生代大小 : s0 ,這點要特別注意。

????? 默認(rèn)情況下,當(dāng)TLAB、eden上分配都失敗時,判斷需要分配的內(nèi)存大小是否 >= eden space的一半大小,如是就直接在老生代上分配;

????? 默認(rèn)情況下的垃圾回收規(guī)則:

????? 1、在回收前PS GC會先檢測之前每次PS GC時,晉升到老生代的平均大小是否大于老生代的剩余空間,如大于則直接觸發(fā)full GC;?
????? 2、在回收后,也會按照上面的規(guī)則進(jìn)行檢測。

????? 默認(rèn)情況下的新生代對象晉升到老生代的規(guī)則:?
???? 1、經(jīng)歷多次minor gc仍存活的對象,可通過以下參數(shù)來控制:AlwaysTenure,默認(rèn)false,表示只要minor GC時存活,就晉升到老生代;NeverTenure,默認(rèn)false,表示永不晉升到老生代;上面兩個都沒設(shè)置的情冴下,如UseAdaptiveSizePolicy,啟動時以InitialTenuringThreshold值作為存活次數(shù)的閾值,在每次ps gc后會動態(tài)調(diào)整,如不使用UseAdaptiveSizePolicy,則以MaxTenuringThreshold為準(zhǔn)。?
???? 2、to space放不下的,直接放入老生代。

???? 在回收后,如UseAdaptiveSizePolicy,PS GC會根據(jù)運(yùn)行狀態(tài)動態(tài)調(diào)整eden、to以及TenuringThreshold的大小。如果不希望動態(tài)調(diào)整可設(shè)置-XX:-UseAdaptiveSizePolicy。如希望跟蹤每次的變化情況,可在啟勱參數(shù)上增加: PrintAdaptiveSizePolicy。

二、老生代可用GC

1、串行GC(Serial Copying):client方式下默認(rèn)GC方式,可通過-XX:+UseSerialGC強(qiáng)制指定。

??? 觸發(fā)機(jī)制匯總:?
? ? 1)old gen空間不足;?
?? 2)perm gen空間不足;?
?? 3)minor gc時的悲觀策略;?
?? 4)minor GC后在eden上分配內(nèi)存仍然失敗;?
?? 5)執(zhí)行heap dump時;?
?? 6)外部調(diào)用System.gc,可通過-XX:+DisableExplicitGC來禁止。

2、并行回收GC(Parallel Scavenge): server模式下默認(rèn)GC方式,可通過-XX:+UseParallelGC強(qiáng)制指定; 并行的線程數(shù)為當(dāng)cpu core<=8 ? cpu core : 3+(cpu core*5)/8或通過 -XX:ParallelGCThreads=x 來強(qiáng)制指定。如ScavengeBeforeFullGC為true(默認(rèn)值),則先執(zhí)行minor GC。

3、并行Compacting:可通過 -XX:+UseParallelOldGC 強(qiáng)制指定。

4、并發(fā)CMS:可通過 -XX:+UseConcMarkSweepGC 來強(qiáng)制指定。并發(fā)的線程數(shù)默認(rèn)為:( 并行GC線程數(shù)+3)/4,也可通過ParallelCMSThreads指定。

??? 觸發(fā)機(jī)制:?
??? 1、當(dāng)老生代空間的使用到達(dá)一定比率時觸發(fā);

???? Hotspot V 1.6中默認(rèn)為65%,可通過PrintCMSInitiationStatistics(此參數(shù)在V 1.5中不能用)來查看這個值到底是多少;可通過CMSInitiatingOccupancyFraction來強(qiáng)制指定,默認(rèn)值并不是賦值在了這個值上,是根據(jù)如下公式計算出來的: ((100 - MinHeapFreeRatio) +(double)(CMSTriggerRatio * MinHeapFreeRatio) / 100.0)/ 100.0; 其中,MinHeapFreeRatio默認(rèn)值: 40?? CMSTriggerRatio默認(rèn)值: 80。

???? 2、當(dāng)perm gen采用CMS收集且空間使用到一定比率時觸發(fā);

???? perm gen采用CMS收集需設(shè)置:-XX:+CMSClassUnloadingEnabled?? Hotspot V 1.6中默認(rèn)為65%;可通過CMSInitiatingPermOccupancyFraction來強(qiáng)制指定,同樣,它是根據(jù)如下公式計算出來的:((100 - MinHeapFreeRatio) +(double)(CMSTriggerPermRatio* MinHeapFreeRatio) / 100.0)/ 100.0; 其中,MinHeapFreeRatio默認(rèn)值: 40??? CMSTriggerPermRatio默認(rèn)值: 80。

????? 3、Hotspot根據(jù)成本計算決定是否需要執(zhí)行CMS GC;可通過-XX:+UseCMSInitiatingOccupancyOnly來去掉這個動態(tài)執(zhí)行的策略。?
????? 4、外部調(diào)用了System.gc,且設(shè)置了ExplicitGCInvokesConcurrent;需要注意,在hotspot 6中,在這種情況下如應(yīng)用同時使用了NIO,可能會出現(xiàn)bug。

6、GC組合

1)默認(rèn)GC組合

探秘Java虛擬機(jī) gc的監(jiān)控

2)可選的GC組合

探秘Java虛擬機(jī) gc的監(jiān)控

7、GC監(jiān)測

1)jstat –gcutil [pid] [intervel] [count]?
2)-verbose:gc // 可以輔助輸出一些詳細(xì)的GC信息;-XX:+PrintGCDetails // 輸出GC詳細(xì)信息;-XX:+PrintGCApplicationStoppedTime // 輸出GC造成應(yīng)用暫停的時間?
-XX:+PrintGCDateStamps // GC發(fā)生的時間信息;-XX:+PrintHeapAtGC // 在GC前后輸出堆中各個區(qū)域的大小;-Xloggc:[file] // 將GC信息輸出到單獨(dú)的文件中,建議都加上,這個消耗不大,而且對查問題和調(diào)優(yōu)有很大的幫助。gc的日志拿下來后可使用GCLogViewer或gchisto進(jìn)行分析。?
3)圖形化的情況下可直接用jvisualvm進(jìn)行分析。

4)查看內(nèi)存的消耗狀況

????? (1)長期消耗,可以直接dump,然后MAT(內(nèi)存分析工具)查看即可

????? (2)短期消耗,圖形界面情況下,可使用jvisualvm的memory profiler或jprofiler。

8、系統(tǒng)調(diào)優(yōu)方法

步驟:1、評估現(xiàn)狀 2、設(shè)定目標(biāo) 3、嘗試調(diào)優(yōu) 4、衡量調(diào)優(yōu) 5、細(xì)微調(diào)整

設(shè)定目標(biāo):

1)降低Full GC的執(zhí)行頻率??
2)降低Full GC的消耗時間??
3)降低Full GC所造成的應(yīng)用停頓時間??
4)降低Minor GC執(zhí)行頻率??
5)降低Minor GC消耗時間??
例如某系統(tǒng)的GC調(diào)優(yōu)目標(biāo):降低Full GC執(zhí)行頻率的同時,盡可能降低minor GC的執(zhí)行頻率、消耗時間以及GC對應(yīng)用造成的停頓時間。

衡量調(diào)優(yōu):

1、衡量工具?
1)打印GC日志信息:-XX:+PrintGCDetails –XX:+PrintGCApplicationStoppedTime -Xloggc: {文件名}? -XX:+PrintGCTimeStamps?
2)jmap:(由于每個版本jvm的默認(rèn)值可能會有改變,建議還是用jmap首先觀察下目前每個代的內(nèi)存大小、GC方式) ??
3)運(yùn)行狀況監(jiān)測工具:jstat、jvisualvm、sar 、gclogviewer

2、應(yīng)收集的信息?
1)minor gc的執(zhí)行頻率;full gc的執(zhí)行頻率,每次GC耗時多少??
2)高峰期什么狀況??
3)minor gc回收的效果如何?survivor的消耗狀況如何,每次有多少對象會進(jìn)入老生代??
4)full gc回收的效果如何?(簡單的 memory leak 判斷方法)?
5)系統(tǒng)的load、cpu消耗、qps or tps、響應(yīng)時間

QPS每秒查詢率:是對一個特定的查詢服務(wù)器在規(guī)定時間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn)。在因特網(wǎng)上,作為域名服務(wù)器的機(jī)器性能經(jīng)常用每秒查詢率來衡量。對應(yīng)fetches/sec,即每秒的響應(yīng)請求數(shù),也即是最大吞吐能力。?
TPS(Transaction Per Second):每秒鐘系統(tǒng)能夠處理的交易或事務(wù)的數(shù)量。

嘗試調(diào)優(yōu):

注意Java RMI的定時GC觸發(fā)機(jī)制,可通過:-XX:+DisableExplicitGC來禁止或通過 -Dsun.rmi.dgc.server.gcInterval=3600000來控制觸發(fā)的時間。

1)降低Full GC執(zhí)行頻率 – 通常瓶頸?
老生代本身占用的內(nèi)存空間就一直偏高,所以只要稍微放點對象到老生代,就full GC了;?
通常原因:系統(tǒng)緩存的東西太多;?
例如:使用oracle 10g驅(qū)動時preparedstatement cache太大;?
查找辦法:現(xiàn)執(zhí)行Dump然后再進(jìn)行MAT分析;

(1)Minor GC后總是有對象不斷的進(jìn)入老生代,導(dǎo)致老生代不斷的滿?
通常原因:Survivor太小了?
系統(tǒng)表現(xiàn):系統(tǒng)響應(yīng)太慢、請求量太大、每次請求分配的內(nèi)存太多、分配的對象太大...?
查找辦法:分析兩次minor GC之間到底哪些地方分配了內(nèi)存;?
利用jstat觀察Survivor的消耗狀況,-XX:PrintHeapAtGC,輸出GC前后的詳細(xì)信息;?
對于系統(tǒng)響應(yīng)慢可以采用系統(tǒng)優(yōu)化,不是GC優(yōu)化的內(nèi)容;

(2)老生代的內(nèi)存占用一直偏高?
調(diào)優(yōu)方法:① 擴(kuò)大老生代的大小(減少新生代的大小或調(diào)大heap的 大小);?
減少new注意對minor gc的影響并且同時有可能造成full gc還是嚴(yán)重;?
調(diào)大heap注意full gc的時間的延長,cpu夠強(qiáng)悍嘛,os是32 bit的嗎??
② 程序優(yōu)化(去掉一些不必要的緩存)

(3)Minor GC后總是有對象不斷的進(jìn)入老生代?
前提:這些進(jìn)入老生代的對象在full GC時大部分都會被回收?
調(diào)優(yōu)方法:?
① 降低Minor GC的執(zhí)行頻率;?
② 讓對象盡量在Minor GC中就被回收掉:增大Eden區(qū)、增大survivor、增大TenuringThreshold;注意這些可能會造成minor gc執(zhí)行頻繁;?
③ 切換成CMS GC:老生代還沒有滿就回收掉,從而降低Full GC觸發(fā)的可能性;?
④ 程序優(yōu)化:提升響應(yīng)速度、降低每次請求分配的內(nèi)存、

(4)降低單次Full GC的執(zhí)行時間?
通常原因:老生代太大了...?
調(diào)優(yōu)方法:1)是并行GC嗎??? 2)升級CPU? 3)減小Heap或老生代

(5)降低Minor GC執(zhí)行頻率?
通常原因:每次請求分配的內(nèi)存多、請求量大?
通常辦法:1)擴(kuò)大heap、擴(kuò)大新生代、擴(kuò)大eden。注意點:降低每次請求分配的內(nèi)存;橫向增加機(jī)器的數(shù)量分擔(dān)請求的數(shù)量。

(6)降低Minor GC執(zhí)行時間?
通常原因:新生代太大了,響應(yīng)速度太慢了,導(dǎo)致每次Minor GC時存活的對象多?
通常辦法:1)減小點新生代吧;2)增加CPU的數(shù)量、升級CPU的配置;加快系統(tǒng)的響應(yīng)速度

細(xì)微調(diào)整:

首先需要了解以下情況:

① 當(dāng)響應(yīng)速度下降到多少或請求量上漲到多少時,系統(tǒng)會宕掉?

② 參數(shù)調(diào)整后系統(tǒng)多久會執(zhí)行一次Minor GC,多久會執(zhí)行一次Full GC,高峰期會如何?

需要計算的量:

①每次請求平均需要分配多少內(nèi)存?系統(tǒng)的平均響應(yīng)時間是多少呢?請求量是多少、多常時間執(zhí)行一次Minor GC、Full GC?

②現(xiàn)有參數(shù)下,應(yīng)該是多久一次Minor GC、Full GC,對比真實狀況,做一定的調(diào)整;

必殺技:提升響應(yīng)速度、降低每次請求分配的內(nèi)存?

9、系統(tǒng)調(diào)優(yōu)舉例

???? 現(xiàn)象:1、系統(tǒng)響應(yīng)速度大概為100ms;2、當(dāng)系統(tǒng)QPS增長到40時,機(jī)器每隔5秒就執(zhí)行一次minor gc,每隔3分鐘就執(zhí)行一次full gc,并且很快就一直full GC了;4、每次Full gc后舊生代大概會消耗400M,有點多了。

???? 解決方案:解決Full GC次數(shù)過多的問題

??? (1)降低響應(yīng)時間或請求次數(shù),這個需要重構(gòu),比較麻煩;——這個是終極方法,往往能夠順利的解決問題,因為大部分的問題均是由程序自身造成的。

??? (2)減少老生代內(nèi)存的消耗,比較靠譜;——可以通過分析Dump文件(jmap dump),并利用MAT查找內(nèi)存消耗的原因,從而發(fā)現(xiàn)程序中造成老生代內(nèi)存消耗的原因。

??? (3)減少每次請求的內(nèi)存的消耗,貌似比較靠譜;——這個是海市蜃樓,沒有太好的辦法。

??? (4)降低GC造成的應(yīng)用暫停的時間——可以采用CMS GS垃圾回收器。參數(shù)設(shè)置如下:

???? -Xms1536m -Xmx1536m -Xmn700m -XX:SurvivorRatio=7 -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection

???? -XX:CMSMaxAbortablePrecleanTime=1000 -XX:+CMSClassUnloadingEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:+DisableExplicitGC

??? (5)減少每次minor gc晉升到old的對象。可選方法:1) 調(diào)大新生代。2)調(diào)大Survivor。3)調(diào)大TenuringThreshold。

????? 調(diào)大Survivor:當(dāng)前采用PS GC,Survivor space會被動態(tài)調(diào)整。由于調(diào)整幅度很小,導(dǎo)致了經(jīng)常有對象直接轉(zhuǎn)移到了老生代;于是禁止Survivor區(qū)的動態(tài)調(diào)整了,-XX:-UseAdaptiveSizePolicy,并計算Survivor Space需要的大小,于是繼續(xù)觀察,并做微調(diào)…。最終將Full GC推遲到2小時1次。

10、垃圾回收的實現(xiàn)原理

????? 內(nèi)存回收的實現(xiàn)方法:1)引用計數(shù):不適合復(fù)雜對象的引用關(guān)系,尤其是循環(huán)依賴的場景。2)有向圖Tracing:適合于復(fù)雜對象的引用關(guān)系場景,Hotspot采用這種。常用算法:Copying、Mark-Sweep、Mark-Compact。

????? Hotspot從root set開始掃描有引用的對象并對Reference類型的對象進(jìn)行特殊處理。?
????? 以下是Root Set的列表:1)當(dāng)前正在執(zhí)行的線程;2)全局/靜態(tài)變量;3)JVM Handles;4)JNI 【 Java Native Interface 】Handles;

????? 另外:minor GC只掃描新生代,當(dāng)老生代的對象引用了新生代的對象時,會采用如下的處理方式:在給對象賦引用時,會經(jīng)過一個write barrier的過程,以便檢查是否有老生代引用新生代對象的情況,如有則記錄到remember set中。并在minor gc時,remember set指向的新生代對象也作為root set。

????? 新生代串行GC(Serial Copying):

???? 新生代串行GC(Serial Copying)完整內(nèi)存的分配策略:

???? 1)首先在TLAB(本地線程分配緩沖區(qū))上嘗試分配;?
???? 2)檢查是否需要在新生代上分配,如需要分配的大小小于PretenureSizeThreshold,則在eden區(qū)上進(jìn)行分配,分配成功則返回;分配失敗則繼續(xù);?
???? 3)檢查是否需要嘗試在老生代上分配,如需要,則遍歷所有代并檢查是否可在該代上分配,如可以則進(jìn)行分配;如不需要在老生代上嘗試分配,則繼續(xù);?
???? 4)根據(jù)策略決定執(zhí)行新生代GC或Full GC,執(zhí)行full gc時不清除soft Ref;?
???? 5)如需要分配的大小大于PretenureSizeThreshold,嘗試在老生代上分配,否則嘗試在新生代上分配;?
???? 6)嘗試擴(kuò)大堆并分配;?
???? 7)執(zhí)行full gc,并清除所有soft Ref,按步驟5繼續(xù)嘗試分配。??

???? 新生代串行GC(Serial Copying)完整內(nèi)存回收策略?
???? 1)檢查to是否為空,不為空返回false;?
???? 2)檢查老生代剩余空間是否大于當(dāng)前eden+from已用的大小,如大于則返回true,如小于且HandlePromotionFailure為true,則檢查剩余空間是否大于之前每次minor gc晉級到老生代的平均大小,如大于返回true,如小于返回false。?
???? 3)如上面的結(jié)果為false,則執(zhí)行full gc;如上面的結(jié)果為true,執(zhí)行下面的步驟;?
???? 4)掃描引用關(guān)系,將活的對象copy到to space,如對象在minor gc中的存活次數(shù)超過tenuring_threshold或分配失敗,則往老生代復(fù)制,如仍然復(fù)制失敗,則取決于HandlePromotionFailure,如不需要處理,直接拋出OOM,并退出vm,如需處理,則保持這些新生代對象不動;

???? 新生代可用GC-PS

??? 完整內(nèi)存分配策略?
??? 1)先在TLAB上分配,分配失敗則直接在eden上分配;?
??? 2)當(dāng)eden上分配失敗時,檢查需要分配的大小是否 >= eden space的一半,如是,則直接在老生代分配;?
??? 3)如分配仍然失敗,且gc已超過頻率,則拋出OOM;?
??? 4)進(jìn)入基本分配策略失敗的模式;?
??? 5)執(zhí)行PS GC,在eden上分配;?
??? 6)執(zhí)行非最大壓縮的full gc,在eden上分配;?
??? 7)在舊生代上分配;?
??? 8)執(zhí)行最大壓縮full gc,在eden上分配;?
??? 9)在舊生代上分配;?
??? 10)如還失敗,回到2。

?? 最悲慘的情況,分配觸發(fā)多次PS GC和多次Full GC,直到OOM。

?? 完整內(nèi)存回收策略?
?? 1)如gc所執(zhí)行的時間超過,直接結(jié)束;?
?? 2)先調(diào)用invoke_nopolicy?
?????? 2.1 先檢查是不是要嘗試scavenge;?
?????? 2.1.1 to space必須為空,如不為空,則返回false;?
?????? 2.1.2 獲取之前所有minor gc晉級到old的平均大小,并對比目前eden+from已使用的大小,取更小的一個值,如老生代剩余空間小于此值,則返回false,如大于則返回true;?
?????? 2.2 如不需要嘗試scavenge,則返回false,否則繼續(xù);?
?????? 2.3 多線程掃描活的對象,并基亍copying算法回收,回收時相應(yīng)的晉升對象到舊生代;?
?????? 2.4 如UseAdaptiveSizePolicy,那么重新計算to space和tenuringThreshold的值,并調(diào)整。?
?? 3)如invoke_nopolicy返回的是false,或之前所有minor gc晉級到老生代的平均大小 &gt; 舊生代的剩余空間,那么繼續(xù)下面的步驟,否則結(jié)束;?
?? 4)如UseParallelOldGC,則執(zhí)行PSParallelCompact,如不是UseParallelOldGC,則執(zhí)行PSMarkSweep。

???? 老生代并行CMS GC:

??? 優(yōu)缺點:

???? 1) 大部分時候和應(yīng)用并發(fā)進(jìn)行,因此只會造成很短的暫停時間;?
??? 2)浮動垃圾,沒辦法,所以內(nèi)存空間要稍微大一點;?
??? 3)內(nèi)存碎片,-XX:+UseCMSCompactAtFullCollection 來解決;?
??? 4) 爭搶CPU,這GC方式就這樣;?
??? 5)多次remark,所以總的gc時間會比并行的長;?
??? 6)內(nèi)存分配,free list方式,so性能稍差,對minor GC會有一點影響;?
??? 7)和應(yīng)用并發(fā),有可能分配和回收同時,產(chǎn)生競爭,引入了鎖,JVM分配優(yōu)先。

11、TLAB的解釋

???? 堆內(nèi)的對象數(shù)據(jù)是各個線程所共享的,所以當(dāng)在堆內(nèi)創(chuàng)建新的對象時,就需要進(jìn)行鎖操作。鎖操作是比較耗時,因此JVM為每個線在堆上分配了一塊“自留地”——TLAB(全稱是Thread Local Allocation Buffer),位于堆內(nèi)存的新生代,也就是Eden區(qū)。每個線程在創(chuàng)建新的對象時,會首先嘗試在自己的TLAB里進(jìn)行分配,如果成功就返回,失敗了再到共享的Eden區(qū)里去申請空間。在線程自己的TLAB區(qū)域創(chuàng)建對象失敗一般有兩個原因:一是對象太大,二是自己的TLAB區(qū)剩余空間不夠。通常默認(rèn)的TLAB區(qū)域大小是Eden區(qū)域的1%,當(dāng)然也可以手工進(jìn)行調(diào)整,對應(yīng)的JVM參數(shù)是-XX:TLABWasteTargetPercent。

附表:

?

JVM參數(shù)的含義:

參數(shù)名稱
含義
默認(rèn)值 ?
-Xms 初始堆大小 物理內(nèi)存的1/64(<1GB) 默認(rèn)(MinHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存小于40%時,JVM就會增大堆直到-Xmx的最大限制.
-Xmx 最大堆大小 物理內(nèi)存的1/4(<1GB) 默認(rèn)(MaxHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存大于70%時,JVM會減少堆直到 -Xms的最小限制
-Xmn 年輕代大小(1.4or lator) ? 注意: 此處的大小是(eden+ 2 survivor space).與jmap -heap中顯示的New gen是不同的。
整個堆大小=年輕代大小 + 年老代大小 + 持久代大小.
增大年輕代后,將會減小年老代大小.此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8
-XX:NewSize 設(shè)置年輕代大小(for 1.3/1.4) ? ?
-XX:MaxNewSize 年輕代最大值(for 1.3/1.4) ? ?
-XX:PermSize 設(shè)置持久代(perm gen)初始值 物理內(nèi)存的1/64 ?
-XX:MaxPermSize 設(shè)置持久代最大值 物理內(nèi)存的1/4 ?
-Xss 每個線程的堆棧大小 ? JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K.更具應(yīng)用的線程所需內(nèi)存大小進(jìn)行 調(diào)整.在相同物理內(nèi)存下,減小這個值能生成更多的線程.但是操作系統(tǒng)對一個進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在3000~5000左右
一般小的應(yīng)用, 如果棧不是很深, 應(yīng)該是128k夠用的 大的應(yīng)用建議使用256k。這個選項對性能影響比較大,需要嚴(yán)格的測試。(校長)
和threadstacksize選項解釋很類似,官方文檔似乎沒有解釋,在論壇中有這樣一句話:"”
-Xss is translated in a VM flag named ThreadStackSize”
一般設(shè)置這個值就可以了。
-XX:ThreadStackSize Thread Stack Size ? (0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.]
-XX:NewRatio 年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(除去持久代) ? -XX:NewRatio=4表示年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5
Xms=Xmx并且設(shè)置了Xmn的情況下,該參數(shù)不需要進(jìn)行設(shè)置。
-XX:SurvivorRatio Eden區(qū)與Survivor區(qū)的大小比值 ? 設(shè)置為8,則兩個Survivor區(qū)與一個Eden區(qū)的比值為2:8,一個Survivor區(qū)占整個年輕代的1/10
-XX:LargePageSizeInBytes 內(nèi)存頁的大小不可設(shè)置過大, 會影響Perm的大小 ? =128m
-XX:+UseFastAccessorMethods 原始類型的快速優(yōu)化 ? ?
-XX:+DisableExplicitGC 關(guān)閉System.gc() ? 這個參數(shù)需要嚴(yán)格的測試
-XX:MaxTenuringThreshold 垃圾最大年齡 ? 如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進(jìn)入年老代. 對于年老代比較多的應(yīng)用,可以提高效率.如果將此值設(shè)置為一個較大值,則年輕代對象會在Survivor區(qū)進(jìn)行多次復(fù)制,這樣可以增加對象再年輕代的存活 時間,增加在年輕代即被回收的概率
該參數(shù)只有在串行GC時才有效.
-XX:+AggressiveOpts 加快編譯 ? ?
-XX:+UseBiasedLocking 鎖機(jī)制的性能改善 ? ?
-Xnoclassgc 禁用垃圾回收 ? ?
-XX:SoftRefLRUPolicyMSPerMB 每兆堆空閑空間中SoftReference的存活時間 1s softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap
-XX:PretenureSizeThreshold 對象超過多大是直接在舊生代分配 0 單位字節(jié) 新生代采用Parallel Scavenge GC時無效
另一種直接在舊生代分配的情況是大的數(shù)組對象,且數(shù)組中無外部引用對象.
-XX:TLABWasteTargetPercent TLAB占eden區(qū)的百分比 1% ?
-XX:+CollectGen0First FullGC時是否先YGC

false

?

并行收集器相關(guān)參數(shù)

參數(shù)名稱 含義 默認(rèn)值 ?
-Xms 初始堆大小 物理內(nèi)存的1/64(<1GB) 默認(rèn)(MinHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存小于40%時,JVM就會增大堆直到-Xmx的最大限制.
-Xmx 最大堆大小 物理內(nèi)存的1/4(<1GB) 默認(rèn)(MaxHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存大于70%時,JVM會減少堆直到 -Xms的最小限制
-Xmn 年輕代大小(1.4or lator) ? 注意 :此處的大小是(eden+ 2 survivor space).與jmap -heap中顯示的New gen是不同的。
整個堆大小=年輕代大小 + 年老代大小 + 持久代大小.
增大年輕代后,將會減小年老代大小.此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8
-XX:NewSize 設(shè)置年輕代大小(for 1.3/1.4) ? ?
-XX:MaxNewSize 年輕代最大值(for 1.3/1.4) ? ?
-XX:PermSize 設(shè)置持久代(perm gen)初始值 物理內(nèi)存的1/64 ?
-XX:MaxPermSize 設(shè)置持久代最大值 物理內(nèi)存的1/4 ?
-Xss 每個線程的堆棧大小 ? JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K.更具應(yīng)用的線程所需內(nèi)存大小進(jìn)行 調(diào)整.在相同物理內(nèi)存下,減小這個值能生成更多的線程.但是操作系統(tǒng)對一個進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在3000~5000左右
一般小的應(yīng)用, 如果棧不是很深, 應(yīng)該是128k夠用的 大的應(yīng)用建議使用256k。這個選項對性能影響比較大,需要嚴(yán)格的測試。(校長)
和threadstacksize選項解釋很類似,官方文檔似乎沒有解釋,在論壇中有這樣一句話:"”
-Xss is translated in a VM flag named ThreadStackSize”
一般設(shè)置這個值就可以了。
- XX:ThreadStackSize Thread Stack Size ? (0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.]
-XX:NewRatio 年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(除去持久代) ? -XX:NewRatio=4表示年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5
Xms=Xmx并且設(shè)置了Xmn的情況下,該參數(shù)不需要進(jìn)行設(shè)置。
-XX:SurvivorRatio Eden區(qū)與Survivor區(qū)的大小比值 ? 設(shè)置為8,則兩個Survivor區(qū)與一個Eden區(qū)的比值為2:8,一個Survivor區(qū)占整個年輕代的1/10
-XX:LargePageSizeInBytes 內(nèi)存頁的大小不可設(shè)置過大, 會影響Perm的大小 ? =128m
-XX:+UseFastAccessorMethods 原始類型的快速優(yōu)化 ? ?
-XX:+DisableExplicitGC 關(guān)閉System.gc() ? 這個參數(shù)需要嚴(yán)格的測試
-XX:MaxTenuringThreshold 垃圾最大年齡 ? 如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進(jìn)入年老代. 對于年老代比較多的應(yīng)用,可以提高效率.如果將此值設(shè)置為一個較大值,則年輕代對象會在Survivor區(qū)進(jìn)行多次復(fù)制,這樣可以增加對象再年輕代的存活 時間,增加在年輕代即被回收的概率
該參數(shù)只有在串行GC時才有效.
-XX:+AggressiveOpts 加快編譯 ? ?
-XX:+UseBiasedLocking 鎖機(jī)制的性能改善 ? ?
-Xnoclassgc 禁用垃圾回收 ? ?
-XX:SoftRefLRUPolicyMSPerMB 每兆堆空閑空間中SoftReference的存活時間 1s softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap
-XX:PretenureSizeThreshold 對象超過多大是直接在舊生代分配 0 單位字節(jié) 新生代采用Parallel Scavenge GC時無效
另一種直接在舊生代分配的情況是大的數(shù)組對象,且數(shù)組中無外部引用對象.
-XX:TLABWasteTargetPercent TLAB占eden區(qū)的百分比 1% ?
-XX:+ CollectGen0First FullGC時是否先YGC false ?

CMS相關(guān)參數(shù)

-XX:+UseConcMarkSweepGC 使用CMS內(nèi)存收集 ? 測試中配置這個以后,-XX:NewRatio=4的配置失效了,原因不明.所以,此時年輕代大小最好用-Xmn設(shè)置.???
-XX:+AggressiveHeap ? ? 試圖是使用大量的物理內(nèi)存
長時間大內(nèi)存使用的優(yōu)化,能檢查計算資源(內(nèi)存, 處理器數(shù)量)
至少需要256MB內(nèi)存
大量的CPU/內(nèi)存, (在1.4.1在4CPU的機(jī)器上已經(jīng)顯示有提升)
-XX:CMSFullGCsBeforeCompaction 多少次后進(jìn)行內(nèi)存壓縮 ? 由于并發(fā)收集器不對內(nèi)存空間進(jìn)行壓縮,整理,所以運(yùn)行一段時間以后會產(chǎn)生"碎片",使得運(yùn)行效率降低.此值設(shè)置運(yùn)行多少次GC以后對內(nèi)存空間進(jìn)行壓縮,整理.
-XX:+CMSParallelRemarkEnabled 降低標(biāo)記停頓 ? ?
-XX+UseCMSCompactAtFullCollection 在FULL GC的時候, 對年老代的壓縮 ? CMS是不會移動內(nèi)存的, 因此, 這個非常容易產(chǎn)生碎片, 導(dǎo)致內(nèi)存不夠用, 因此, 內(nèi)存的壓縮這個時候就會被啟用。 增加這個參數(shù)是個好習(xí)慣。
可能會影響性能,但是可以消除碎片
-XX:+UseCMSInitiatingOccupancyOnly 使用手動定義初始化定義開始CMS收集 ? 禁止hostspot自行觸發(fā)CMS GC
-XX:CMSInitiatingOccupancyFraction=70 使用cms作為垃圾回收
使用70%后開始CMS收集
92 為了保證不出現(xiàn)promotion failed(見下面介紹)錯誤,該值的設(shè)置需要滿足以下公式: CMSInitiatingOccupancyFraction計算公式
-XX:CMSInitiatingPermOccupancyFraction 設(shè)置Perm Gen使用到達(dá)多少比率時觸發(fā) 92 ?
-XX:+CMSIncrementalMode 設(shè)置為增量模式 ? 用于單CPU情況
-XX:+CMSClassUnloadingEnabled ? ? ?

輔助信息

-XX:+PrintGC ? ?

輸出形式:

[GC 118250K->113543K(130112K), 0.0094143 secs]
[Full GC 121376K->10414K(130112K), 0.0650971 secs]

-XX:+PrintGCDetails ? ?

輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]
[GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

-XX:+PrintGCTimeStamps ? ? ?
-XX:+PrintGC:PrintGCTimeStamps ? ? 可與-XX:+PrintGC -XX:+PrintGCDetails混合使用
輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
-XX:+PrintGCApplicationStoppedTime 打印垃圾回收期間程序暫停的時間.可與上面混合使用 ? 輸出形式:Total time for which application threads were stopped: 0.0468229 seconds
-XX:+PrintGCApplicationConcurrentTime 打印每次垃圾回收前,程序未中斷的執(zhí)行時間.可與上面混合使用 ? 輸出形式:Application time: 0.5291524 seconds
-XX:+PrintHeapAtGC 打印GC前后的詳細(xì)堆棧信息 ? ?
-Xloggc:filename 把相關(guān)日志信息記錄到文件以便分析.
與上面幾個配合使用
? ?

-XX:+PrintClassHistogram

garbage collects before printing the histogram. ? ?
-XX:+PrintTLAB 查看TLAB空間的使用情況 ? ?
XX:+PrintTenuringDistribution 查看每次minor GC后新的存活周期的閾值 ?

Desired survivor size 1048576 bytes, new threshold 7 (max 15)
new threshold 7即標(biāo)識新的存活周期的閾值為7。

?

探秘Java虛擬機(jī) gc的監(jiān)控


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 什邡市| 津南区| 虎林市| 峨山| 吉隆县| 通渭县| 沙洋县| 青龙| 土默特左旗| 两当县| 赤城县| 成武县| 丹东市| 马关县| 广东省| 琼中| 周宁县| 玉门市| 南陵县| 隆子县| 凤冈县| 阳信县| 若尔盖县| 嵊泗县| 鸡东县| 铅山县| 柳州市| 来安县| 临泽县| 宣恩县| 南阳市| 德保县| 仙游县| 南川市| 玉龙| 攀枝花市| 滕州市| 东方市| 通江县| 会泽县| SHOW|