亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

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

系統(tǒng) 2113 0

1、Java虛擬機(jī)運(yùn)行時(shí)的數(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%時(shí),JVM就會(huì)增大堆直到-Xmx的最大限制

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

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

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

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

-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)行時(shí)可通過(guò)jstat –gcutil來(lái)查看堆中各個(gè)內(nèi)存區(qū)域的變化以及GC的工作狀態(tài);?
2)啟動(dòng)時(shí)可添加-XX:+PrintGCDetails? –Xloggc:&lt;file>輸出到日志文件來(lái)查看GC的狀況;?
3)jmap –heap可用于查看各個(gè)內(nèi)存空間的大小;

5)斷代法可用GC匯總

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

一、新生代可用GC

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

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

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

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

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

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

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

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

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

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

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

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

二、老生代可用GC

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

步驟:1、評(píng)估現(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的消耗時(shí)間??
3)降低Full GC所造成的應(yīng)用停頓時(shí)間??
4)降低Minor GC執(zhí)行頻率??
5)降低Minor GC消耗時(shí)間??
例如某系統(tǒng)的GC調(diào)優(yōu)目標(biāo):降低Full GC執(zhí)行頻率的同時(shí),盡可能降低minor GC的執(zhí)行頻率、消耗時(shí)間以及GC對(duì)應(yīng)用造成的停頓時(shí)間。

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

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

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

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

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

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

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

(1)Minor GC后總是有對(duì)象不斷的進(jìn)入老生代,導(dǎo)致老生代不斷的滿?
通常原因:Survivor太小了?
系統(tǒng)表現(xiàn):系統(tǒng)響應(yīng)太慢、請(qǐng)求量太大、每次請(qǐng)求分配的內(nèi)存太多、分配的對(duì)象太大...?
查找辦法:分析兩次minor GC之間到底哪些地方分配了內(nèi)存;?
利用jstat觀察Survivor的消耗狀況,-XX:PrintHeapAtGC,輸出GC前后的詳細(xì)信息;?
對(duì)于系統(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注意對(duì)minor gc的影響并且同時(shí)有可能造成full gc還是嚴(yán)重;?
調(diào)大heap注意full gc的時(shí)間的延長(zhǎng),cpu夠強(qiáng)悍嘛,os是32 bit的嗎??
② 程序優(yōu)化(去掉一些不必要的緩存)

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

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

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

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

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

首先需要了解以下情況:

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

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

需要計(jì)算的量:

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

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

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

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

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

???? 解決方案:解決Full GC次數(shù)過(guò)多的問(wèn)題

??? (1)降低響應(yīng)時(shí)間或請(qǐng)求次數(shù),這個(gè)需要重構(gòu),比較麻煩;——這個(gè)是終極方法,往往能夠順利的解決問(wèn)題,因?yàn)榇蟛糠值膯?wèn)題均是由程序自身造成的。

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

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

??? (4)降低GC造成的應(yīng)用暫停的時(shí)間——可以采用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的對(duì)象。可選方法:1) 調(diào)大新生代。2)調(diào)大Survivor。3)調(diào)大TenuringThreshold。

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

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

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

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

????? 另外:minor GC只掃描新生代,當(dāng)老生代的對(duì)象引用了新生代的對(duì)象時(shí),會(huì)采用如下的處理方式:在給對(duì)象賦引用時(shí),會(huì)經(jīng)過(guò)一個(gè)write barrier的過(guò)程,以便檢查是否有老生代引用新生代對(duì)象的情況,如有則記錄到remember set中。并在minor gc時(shí),remember set指向的新生代對(duì)象也作為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時(shí)不清除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晉級(jí)到老生代的平均大小,如大于返回true,如小于返回false。?
???? 3)如上面的結(jié)果為false,則執(zhí)行full gc;如上面的結(jié)果為true,執(zhí)行下面的步驟;?
???? 4)掃描引用關(guān)系,將活的對(duì)象copy到to space,如對(duì)象在minor gc中的存活次數(shù)超過(guò)tenuring_threshold或分配失敗,則往老生代復(fù)制,如仍然復(fù)制失敗,則取決于HandlePromotionFailure,如不需要處理,直接拋出OOM,并退出vm,如需處理,則保持這些新生代對(duì)象不動(dòng);

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

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

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

??? 優(yōu)缺點(diǎn):

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

11、TLAB的解釋

???? 堆內(nèi)的對(duì)象數(shù)據(jù)是各個(gè)線程所共享的,所以當(dāng)在堆內(nèi)創(chuàng)建新的對(duì)象時(shí),就需要進(jìn)行鎖操作。鎖操作是比較耗時(shí),因此JVM為每個(gè)線在堆上分配了一塊“自留地”——TLAB(全稱是Thread Local Allocation Buffer),位于堆內(nèi)存的新生代,也就是Eden區(qū)。每個(gè)線程在創(chuàng)建新的對(duì)象時(shí),會(huì)首先嘗試在自己的TLAB里進(jìn)行分配,如果成功就返回,失敗了再到共享的Eden區(qū)里去申請(qǐng)空間。在線程自己的TLAB區(qū)域創(chuàng)建對(duì)象失敗一般有兩個(gè)原因:一是對(duì)象太大,二是自己的TLAB區(qū)剩余空間不夠。通常默認(rèn)的TLAB區(qū)域大小是Eden區(qū)域的1%,當(dāng)然也可以手工進(jìn)行調(diào)整,對(duì)應(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%時(shí),JVM就會(huì)增大堆直到-Xmx的最大限制.
-Xmx 最大堆大小 物理內(nèi)存的1/4(<1GB) 默認(rèn)(MaxHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存大于70%時(shí),JVM會(huì)減少堆直到 -Xms的最小限制
-Xmn 年輕代大小(1.4or lator) ? 注意: 此處的大小是(eden+ 2 survivor space).與jmap -heap中顯示的New gen是不同的。
整個(gè)堆大小=年輕代大小 + 年老代大小 + 持久代大小.
增大年輕代后,將會(huì)減小年老代大小.此值對(duì)系統(tǒng)性能影響較大,Sun官方推薦配置為整個(gè)堆的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 每個(gè)線程的堆棧大小 ? JDK5.0以后每個(gè)線程堆棧大小為1M,以前每個(gè)線程堆棧大小為256K.更具應(yīng)用的線程所需內(nèi)存大小進(jìn)行 調(diào)整.在相同物理內(nèi)存下,減小這個(gè)值能生成更多的線程.但是操作系統(tǒng)對(duì)一個(gè)進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無(wú)限生成,經(jīng)驗(yàn)值在3000~5000左右
一般小的應(yīng)用, 如果棧不是很深, 應(yīng)該是128k夠用的 大的應(yīng)用建議使用256k。這個(gè)選項(xiàng)對(duì)性能影響比較大,需要嚴(yán)格的測(cè)試。(校長(zhǎng))
和threadstacksize選項(xiàng)解釋很類似,官方文檔似乎沒(méi)有解釋,在論壇中有這樣一句話:"”
-Xss is translated in a VM flag named ThreadStackSize”
一般設(shè)置這個(gè)值就可以了。
-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和兩個(gè)Survivor區(qū))與年老代的比值(除去持久代) ? -XX:NewRatio=4表示年輕代與年老代所占比值為1:4,年輕代占整個(gè)堆棧的1/5
Xms=Xmx并且設(shè)置了Xmn的情況下,該參數(shù)不需要進(jìn)行設(shè)置。
-XX:SurvivorRatio Eden區(qū)與Survivor區(qū)的大小比值 ? 設(shè)置為8,則兩個(gè)Survivor區(qū)與一個(gè)Eden區(qū)的比值為2:8,一個(gè)Survivor區(qū)占整個(gè)年輕代的1/10
-XX:LargePageSizeInBytes 內(nèi)存頁(yè)的大小不可設(shè)置過(guò)大, 會(huì)影響Perm的大小 ? =128m
-XX:+UseFastAccessorMethods 原始類型的快速優(yōu)化 ? ?
-XX:+DisableExplicitGC 關(guān)閉System.gc() ? 這個(gè)參數(shù)需要嚴(yán)格的測(cè)試
-XX:MaxTenuringThreshold 垃圾最大年齡 ? 如果設(shè)置為0的話,則年輕代對(duì)象不經(jīng)過(guò)Survivor區(qū),直接進(jìn)入年老代. 對(duì)于年老代比較多的應(yīng)用,可以提高效率.如果將此值設(shè)置為一個(gè)較大值,則年輕代對(duì)象會(huì)在Survivor區(qū)進(jìn)行多次復(fù)制,這樣可以增加對(duì)象再年輕代的存活 時(shí)間,增加在年輕代即被回收的概率
該參數(shù)只有在串行GC時(shí)才有效.
-XX:+AggressiveOpts 加快編譯 ? ?
-XX:+UseBiasedLocking 鎖機(jī)制的性能改善 ? ?
-Xnoclassgc 禁用垃圾回收 ? ?
-XX:SoftRefLRUPolicyMSPerMB 每兆堆空閑空間中SoftReference的存活時(shí)間 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 對(duì)象超過(guò)多大是直接在舊生代分配 0 單位字節(jié) 新生代采用Parallel Scavenge GC時(shí)無(wú)效
另一種直接在舊生代分配的情況是大的數(shù)組對(duì)象,且數(shù)組中無(wú)外部引用對(duì)象.
-XX:TLABWasteTargetPercent TLAB占eden區(qū)的百分比 1% ?
-XX:+CollectGen0First FullGC時(shí)是否先YGC

false

?

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

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

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

-XX:+UseConcMarkSweepGC 使用CMS內(nèi)存收集 ? 測(cè)試中配置這個(gè)以后,-XX:NewRatio=4的配置失效了,原因不明.所以,此時(shí)年輕代大小最好用-Xmn設(shè)置.???
-XX:+AggressiveHeap ? ? 試圖是使用大量的物理內(nèi)存
長(zhǎng)時(shí)間大內(nèi)存使用的優(yōu)化,能檢查計(jì)算資源(內(nèi)存, 處理器數(shù)量)
至少需要256MB內(nèi)存
大量的CPU/內(nèi)存, (在1.4.1在4CPU的機(jī)器上已經(jīng)顯示有提升)
-XX:CMSFullGCsBeforeCompaction 多少次后進(jìn)行內(nèi)存壓縮 ? 由于并發(fā)收集器不對(duì)內(nèi)存空間進(jìn)行壓縮,整理,所以運(yùn)行一段時(shí)間以后會(huì)產(chǎn)生"碎片",使得運(yùn)行效率降低.此值設(shè)置運(yùn)行多少次GC以后對(duì)內(nèi)存空間進(jìn)行壓縮,整理.
-XX:+CMSParallelRemarkEnabled 降低標(biāo)記停頓 ? ?
-XX+UseCMSCompactAtFullCollection 在FULL GC的時(shí)候, 對(duì)年老代的壓縮 ? CMS是不會(huì)移動(dòng)內(nèi)存的, 因此, 這個(gè)非常容易產(chǎn)生碎片, 導(dǎo)致內(nèi)存不夠用, 因此, 內(nèi)存的壓縮這個(gè)時(shí)候就會(huì)被啟用。 增加這個(gè)參數(shù)是個(gè)好習(xí)慣。
可能會(huì)影響性能,但是可以消除碎片
-XX:+UseCMSInitiatingOccupancyOnly 使用手動(dòng)定義初始化定義開(kāi)始CMS收集 ? 禁止hostspot自行觸發(fā)CMS GC
-XX:CMSInitiatingOccupancyFraction=70 使用cms作為垃圾回收
使用70%后開(kāi)始CMS收集
92 為了保證不出現(xiàn)promotion failed(見(jiàn)下面介紹)錯(cuò)誤,該值的設(shè)置需要滿足以下公式: CMSInitiatingOccupancyFraction計(jì)算公式
-XX:CMSInitiatingPermOccupancyFraction 設(shè)置Perm Gen使用到達(dá)多少比率時(shí)觸發(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 打印垃圾回收期間程序暫停的時(shí)間.可與上面混合使用 ? 輸出形式:Total time for which application threads were stopped: 0.0468229 seconds
-XX:+PrintGCApplicationConcurrentTime 打印每次垃圾回收前,程序未中斷的執(zhí)行時(shí)間.可與上面混合使用 ? 輸出形式:Application time: 0.5291524 seconds
-XX:+PrintHeapAtGC 打印GC前后的詳細(xì)堆棧信息 ? ?
-Xloggc:filename 把相關(guān)日志信息記錄到文件以便分析.
與上面幾個(gè)配合使用
? ?

-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)識(shí)新的存活周期的閾值為7。

?

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


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 一级毛片在线播放免费 | 狠狠久久亚洲欧美专区 | 国产一级毛片在线 | 久草免费在线视频观看 | 爱情片在线观看 | 亚洲综合日韩精品欧美综合区 | 日韩免费一区二区三区 | 日日夜夜免费精品视频 | 91精品日本久久久久久牛牛 | 久久99国产综合精品 | 日韩专区亚洲精品欧美专区 | 成人午夜爱爱爱爱爱 | 高清国产一区二区 | 伊人久久久综在合线久久在播 | 天天做天天爱夜夜爽毛片毛片 | 国产精品国产欧美综合一区 | 国产在线原创剧情麻豆 | 天天干天天摸 | 免费99精品国产自在现线观看 | 国产亚洲免费观看 | 精品啪啪 | www.亚洲成人.com | 99在线热视频只有精品免费 | 午夜精品久久久久久久99热 | 亚洲欧美日韩中文高清一 | 久久国产精品一国产精品 | 色老板女色狠xx网 | 国产欧美日韩中文久久 | 中文字幕 国产 | 国内精品久久久久久久星辰影视 | 香蕉大黄香蕉在线观看 | 视频一区色眯眯视频在线 | 一级片在线免费观看 | 午夜福免费福利在线观看 | 国产精品久久久亚洲第一牛牛 | 国产精品视频国产永久视频 | 亚洲精品一区二区三区在线观看 | 色综合久久久久久久久五月 | 中文字幕无线码中文字幕免费 | 一区二区不卡久久精品 | 久久精品视频大全 |