JVM內(nèi)存模型及垃圾收集策略解析_第1頁(yè)
JVM內(nèi)存模型及垃圾收集策略解析_第2頁(yè)
JVM內(nèi)存模型及垃圾收集策略解析_第3頁(yè)
JVM內(nèi)存模型及垃圾收集策略解析_第4頁(yè)
JVM內(nèi)存模型及垃圾收集策略解析_第5頁(yè)
已閱讀5頁(yè),還剩15頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、JVM內(nèi)存模型及垃圾收集策略解析(1)2010-02-22 08:58 狂放不羈 JavaEye 字號(hào):T | T垃圾收集器策略從20世紀(jì)60年代就已經(jīng)流行起來(lái)了,相比于其他編程語(yǔ)言,Java語(yǔ)言是目前使用最多的依賴于垃圾收集器的語(yǔ)言。AD:WOT2015 互聯(lián)網(wǎng)運(yùn)維與開(kāi)發(fā)者大會(huì) 熱銷搶票JVM內(nèi)存模型是Java的核心技術(shù)之一,之前51CTO曾為大家介紹過(guò)JVM分代垃圾回收策略的基礎(chǔ)概念,現(xiàn)在很多編程語(yǔ)言都引入了類似Java JVM的內(nèi)存模型和垃圾收集器的機(jī)制,下面我們將主要針對(duì)Java中的JVM內(nèi)存模型及垃圾收集的具體策略進(jìn)行綜合的分析。一 JVM內(nèi)存模型1.1

2、 Java棧Java棧是與每一個(gè)線程關(guān)聯(lián)的,JVM在創(chuàng)建每一個(gè)線程的時(shí)候,會(huì)分配一定的??臻g給線程。它主要用來(lái)存儲(chǔ)線程執(zhí)行過(guò)程中的局部變量,方法的返回值,以及方法調(diào)用上下文。??臻g隨著線程的終止而釋放。StackOverflowError:如果在線程執(zhí)行的過(guò)程中,??臻g不夠用,那么JVM就會(huì)拋出此異常,這種情況一般是死遞歸造成的。1.2 堆Java中堆是由所有的線程共享的一塊內(nèi)存區(qū)域,堆用來(lái)保存各種JAVA對(duì)象,比如數(shù)組,線程對(duì)象等。1.2.1 GenerationJVM堆一般又可以分為以下三部分: PermPerm代主要保存class,method,filed對(duì)象,這部門(mén)的空間一般不會(huì)溢出,

3、除非一次性加載了很多的類,不過(guò)在涉及到熱部署的應(yīng)用服務(wù)器的時(shí)候,有時(shí)候會(huì)遇到j(luò)ava.lang.OutOfMemoryError : PermGen space 的錯(cuò)誤,造成這個(gè)錯(cuò)誤的很大原因就有可能是每次都重新部署,但是重新部署后,類的class沒(méi)有被卸載掉,這樣就造成了大量的class對(duì)象保存在了perm中,這種情況下,一般重新啟動(dòng)應(yīng)用服務(wù)器可以解決問(wèn)題。 TenuredTenured區(qū)主要保存生命周期長(zhǎng)的對(duì)象,一般是一些老的對(duì)象,當(dāng)一些對(duì)象在Young復(fù)制轉(zhuǎn)移一定的次數(shù)以后,對(duì)象就會(huì)被轉(zhuǎn)移到Tenured區(qū),一般如果系統(tǒng)中用了application級(jí)別的緩存,緩存中的對(duì)象往往會(huì)被轉(zhuǎn)移到這

4、一區(qū)間。 YoungYoung區(qū)被劃分為三部分,Eden區(qū)和兩個(gè)大小嚴(yán)格相同的Survivor區(qū),其中Survivor區(qū)間中,某一時(shí)刻只有其中一個(gè)是被使用的,另外一個(gè)留做垃圾收集時(shí)復(fù)制對(duì)象用,在Young區(qū)間變滿的時(shí)候,minor GC就會(huì)將存活的對(duì)象移到空閑的Survivor區(qū)間中,根據(jù)JVM的策略,在經(jīng)過(guò)幾次垃圾收集后,任然存活于Survivor的對(duì)象將被移動(dòng)到Tenured區(qū)間。1.2.2 Sizing the GenerationsJVM提供了相應(yīng)的參數(shù)來(lái)對(duì)內(nèi)存大小進(jìn)行配置。正如上面描述,JVM中堆被分為了3個(gè)大的區(qū)間,同時(shí)JVM也提供了一些選項(xiàng)對(duì)Young,Tenured的大小進(jìn)行控

5、制。 Total Heap-Xms :指定了JVM初始啟動(dòng)以后初始化內(nèi)存-Xmx:指定JVM堆得最大內(nèi)存,在JVM啟動(dòng)以后,會(huì)分配-Xmx參數(shù)指定大小的內(nèi)存給JVM,但是不一定全部使用,JVM會(huì)根據(jù)-Xms參數(shù)來(lái)調(diào)節(jié)真正用于JVM的內(nèi)存-Xmx -Xms之差就是三個(gè)Virtual空間的大小 Young Generation-XX:NewRatio=8意味著tenured 和 young的比值8:1,這樣eden+2*survivor=1/9堆內(nèi)存-XX:SurvivorRatio=32意味著eden和一個(gè)survivor的比值是32:1,這樣一個(gè)Survivor就占Young區(qū)的1/34.-X

6、mn 參數(shù)設(shè)置了年輕代的大小 Perm Generation-XX:PermSize=16M -XX:MaxPermSize=64MThread Stack-XX:Xss=128K1.3 堆棧分離的好處呵呵,其它的先不說(shuō)了,就來(lái)說(shuō)說(shuō)面向?qū)ο蟮脑O(shè)計(jì)吧,當(dāng)然除了面向?qū)ο蟮脑O(shè)計(jì)帶來(lái)的維護(hù)性,復(fù)用性和擴(kuò)展性方面的好處外,我們看看面向?qū)ο笕绾吻擅畹睦昧硕褩7蛛x。如果從JAVA內(nèi)存模型的角度去理解面向?qū)ο蟮脑O(shè)計(jì),我們就會(huì)發(fā)現(xiàn)對(duì)象它完美的表示了堆和棧,對(duì)象的數(shù)據(jù)放在堆中,而我們編寫(xiě)的那些方法一般都是運(yùn)行在棧中,因此面向?qū)ο蟮脑O(shè)計(jì)是一種非常完美的設(shè)計(jì)方式,它完美的統(tǒng)一了數(shù)據(jù)存儲(chǔ)和運(yùn)行。二 JAVA垃圾收集器

7、2.1 垃圾收集簡(jiǎn)史垃圾收集提供了內(nèi)存管理的機(jī)制,使得應(yīng)用程序不需要在關(guān)注內(nèi)存如何釋放,內(nèi)存用完后,垃圾收集會(huì)進(jìn)行收集,這樣就減輕了因?yàn)槿藶榈墓芾韮?nèi)存而造成的錯(cuò)誤,比如在C+語(yǔ)言里,出現(xiàn)內(nèi)存泄露時(shí)很常見(jiàn)的。Java語(yǔ)言是目前使用最多的依賴于垃圾收集器的語(yǔ)言,但是垃圾收集器策略從20世紀(jì)60年代就已經(jīng)流行起來(lái)了,比如Smalltalk,Eiffel等編程語(yǔ)言也集成了垃圾收集器的機(jī)制。2.2 常見(jiàn)的垃圾收集策略所有的垃圾收集算法都面臨同一個(gè)問(wèn)題,那就是找出應(yīng)用程序不可到達(dá)的內(nèi)存塊,將其釋放,這里面得不可到達(dá)主要是指應(yīng)用程序已經(jīng)沒(méi)有內(nèi)存塊的引用了,而在JAVA中,某個(gè)對(duì)象對(duì)應(yīng)用程序是可到達(dá)的是指:這

8、個(gè)對(duì)象被根(根主要是指類的靜態(tài)變量,或者活躍在所有線程棧的對(duì)象的引用)引用或者對(duì)象被另一個(gè)可到達(dá)的對(duì)象引用。2.2.1 Reference Counting(引用計(jì)數(shù)) 引用計(jì)數(shù)是最簡(jiǎn)單直接的一種方式,這種方式在每一個(gè)對(duì)象中增加一個(gè)引用的計(jì)數(shù),這個(gè)計(jì)數(shù)代表當(dāng)前程序有多少個(gè)引用引用了此對(duì)象,如果此對(duì)象的引用計(jì)數(shù)變?yōu)?,那么此對(duì)象就可以作為垃圾收集器的目標(biāo)對(duì)象來(lái)收集。優(yōu)點(diǎn):簡(jiǎn)單,直接,不需要暫停整個(gè)應(yīng)用缺點(diǎn):1.需要編譯器的配合,編譯器要生成特殊的指令來(lái)進(jìn)行引用計(jì)數(shù)的操作,比如每次將對(duì)象賦值給新的引用,或者者對(duì)象的引用超出了作用域等。2.不能處理循環(huán)引用的問(wèn)題2.2.2 跟蹤收集器跟蹤收

9、集器首先要暫停整個(gè)應(yīng)用程序,然后開(kāi)始從根對(duì)象掃描整個(gè)堆,判斷掃描的對(duì)象是否有對(duì)象引用,這里面有三個(gè)問(wèn)題需要搞清楚:1如果每次掃描整個(gè)堆,那么勢(shì)必讓GC的時(shí)間變長(zhǎng),從而影響了應(yīng)用本身的執(zhí)行。因此在JVM里面采用了分代收集,在新生代收集的時(shí)候minor gc只需要掃描新生代,而不需要掃描老生代。2JVM采用了分代收集以后,minor gc只掃描新生代,但是minor gc怎么判斷是否有老生代的對(duì)象引用了新生代的對(duì)象,JVM采用了卡片標(biāo)記的策略,卡片標(biāo)記將老生代分成了一塊一塊的,劃分以后的每一個(gè)塊就叫做一個(gè)卡片,JVM采用卡表維護(hù)了每一個(gè)塊的狀態(tài),當(dāng)JAVA程序運(yùn)行的時(shí)候,如果發(fā)現(xiàn)老生代對(duì)象引用或者

10、釋放了新生代對(duì)象的引用,那么就JVM就將卡表的狀態(tài)設(shè)置為臟狀態(tài),這樣每次minor gc的時(shí)候就會(huì)只掃描被標(biāo)記為臟狀態(tài)的卡片,而不需要掃描整個(gè)堆。具體如下圖:3GC在收集一個(gè)對(duì)象的時(shí)候會(huì)判斷是否有引用指向?qū)ο?,在JAVA中的引用主要有四種:Strong reference,Soft reference,Weak reference,Phantom reference. Strong Reference強(qiáng)引用是JAVA中默認(rèn)采用的一種方式,我們平時(shí)創(chuàng)建的引用都屬于強(qiáng)引用。如果一個(gè)對(duì)象沒(méi)有強(qiáng)引用,那么對(duì)象就會(huì)被回收。1. public void testStrongRefere

11、nce()  2. Object referent = new Object();  3. Object strongReference = referent;  4. referent = null;  5. System.gc();  6. assertNotNull(strongReference);  7.   Soft Reference軟引用的對(duì)象在GC的時(shí)候不會(huì)被回收,只有當(dāng)內(nèi)存不夠用的時(shí)候才會(huì)真正的回收,因此軟引用適合緩

12、存的場(chǎng)合,這樣使得緩存中的對(duì)象可以盡量的再內(nèi)存中待長(zhǎng)久一點(diǎn)。1. Public void testSoftReference()  2. String  str =  "test"  3. SoftReference<String> softreference = new SoftReference<String>(str);  4. str=null;  5. System.gc();  6

13、. assertNotNull(softreference.get();  7.   Weak reference弱引用有利于對(duì)象更快的被回收,假如一個(gè)對(duì)象沒(méi)有強(qiáng)引用只有弱引用,那么在GC后,這個(gè)對(duì)象肯定會(huì)被回收。1. Public void testWeakReference()  2. String  str =  "test"  3. WeakReference<String> weakReference = new&

14、#160;WeakReference<String>(str);  4. str=null;  5. System.gc();  6. assertNull(weakReference.get();  7.   Phantom reference Mark-Sweep Collector(標(biāo)記-清除收集器)標(biāo)記清除收集器最早由Lisp的發(fā)明人于1960年提出,標(biāo)記清除收集器停止所有的工作,從根掃描每個(gè)活躍的對(duì)象,然后標(biāo)記掃描過(guò)的對(duì)象,標(biāo)記完成以后,清除那些沒(méi)有被標(biāo)記的對(duì)象。優(yōu)點(diǎn):1 解決循環(huán)引用的問(wèn)題2 不需要編譯器的

15、配合,從而就不執(zhí)行額外的指令缺點(diǎn):1每個(gè)活躍的對(duì)象都要進(jìn)行掃描,收集暫停的時(shí)間比較長(zhǎng)。 Copying Collector(復(fù)制收集器)復(fù)制收集器將內(nèi)存分為兩塊一樣大小空間,某一個(gè)時(shí)刻,只有一個(gè)空間處于活躍的狀態(tài),當(dāng)活躍的空間滿的時(shí)候,GC就會(huì)將活躍的對(duì)象復(fù)制到未使用的空間中去,原來(lái)不活躍的空間就變?yōu)榱嘶钴S的空間。復(fù)制收集器具體過(guò)程可以參考下圖:優(yōu)點(diǎn):1 只掃描可以到達(dá)的對(duì)象,不需要掃描所有的對(duì)象,從而減少了應(yīng)用暫停的時(shí)間缺點(diǎn):1需要額外的空間消耗,某一個(gè)時(shí)刻,總是有一塊內(nèi)存處于未使用狀態(tài)2復(fù)制對(duì)象需要一定的開(kāi)銷 Mark-Compact Collector(標(biāo)記-

16、整理收集器)標(biāo)記整理收集器汲取了標(biāo)記清除和復(fù)制收集器的優(yōu)點(diǎn),它分兩個(gè)階段執(zhí)行,在第一個(gè)階段,首先掃描所有活躍的對(duì)象,并標(biāo)記所有活躍的對(duì)象,第二個(gè)階段首先清除未標(biāo)記的對(duì)象,然后將活躍的的對(duì)象復(fù)制到堆得底部。標(biāo)記整理收集器的過(guò)程示意圖請(qǐng)參考下圖:Mark-compact策略極大的減少了內(nèi)存碎片,并且不需要像Copy Collector一樣需要兩倍的空間。2.3 JVM的垃圾收集策略 GC的執(zhí)行時(shí)要耗費(fèi)一定的CPU資源和時(shí)間的,因此在JDK1.2以后,JVM引入了分代收集的策略,其中對(duì)新生代采用"Mark-Compact"策略,而對(duì)老生代采用了“Mark-Sweep&q

17、uot;的策略。其中新生代的垃圾收集器命名為“minor gc”,老生代的GC命名為"Full Gc 或者M(jìn)ajor GC".其中用System.gc()強(qiáng)制執(zhí)行的是Full Gc.2.3.1 Serial CollectorSerial Collector是指任何時(shí)刻都只有一個(gè)線程進(jìn)行垃圾收集,這種策略有一個(gè)名字“stop the whole world",它需要停止整個(gè)應(yīng)用的執(zhí)行。這種類型的收集器適合于單CPU的機(jī)器。Serial Copying Collector此種GC用-XX:UseSerialGC選項(xiàng)配置,它只用于新生代對(duì)象的收集。1.5.0以后。-X

18、X:MaxTenuringThreshold來(lái)設(shè)置對(duì)象復(fù)制的次數(shù)。當(dāng)eden空間不夠的時(shí)候,GC會(huì)將eden的活躍對(duì)象和一個(gè)名叫From survivor空間中尚不夠資格放入Old代的對(duì)象復(fù)制到另外一個(gè)名字叫To Survivor的空間。而此參數(shù)就是用來(lái)說(shuō)明到底From survivor中的哪些對(duì)象不夠資格,假如這個(gè)參數(shù)設(shè)置為31,那么也就是說(shuō)只有對(duì)象復(fù)制31次以后才算是有資格的對(duì)象。這里需要注意幾個(gè)個(gè)問(wèn)題:  From Survivor和To survivor的角色是不斷的變化的,同一時(shí)間只有一塊空間處于使用狀態(tài),這個(gè)空間就叫做From Survivor區(qū),當(dāng)復(fù)制一次后角色就發(fā)生了

19、變化。  如果復(fù)制的過(guò)程中發(fā)現(xiàn)To survivor空間已經(jīng)滿了,那么就直接復(fù)制到old generation.  比較大的對(duì)象也會(huì)直接復(fù)制到Old generation,在開(kāi)發(fā)中,我們應(yīng)該盡量避免這種情況的發(fā)生。Serial  Mark-Compact Collector串行的標(biāo)記-整理收集器是JDK5 update6之前默認(rèn)的老生代的垃圾收集器,此收集使得內(nèi)存碎片最少化,但是它需要暫停的時(shí)間比較長(zhǎng)。2.3.2 Parallel Collector Parallel Collector主要是為了應(yīng)對(duì)多CPU,大數(shù)據(jù)量的環(huán)境。Parallel Colle

20、ctor又可以分為以下兩種:Parallel Copying Collector此種GC用-XX:UseParNewGC參數(shù)配置,它主要用于新生代的收集,此GC可以配合CMS一起使用。1.4.1以后Parallel Mark-Compact Collector,此種GC用-XX:UseParallelOldGC參數(shù)配置,此GC主要用于老生代對(duì)象的收集。1.6.0Parallel scavenging Collector此種GC用-XX:UseParallelGC參數(shù)配置,它是對(duì)新生代對(duì)象的垃圾收集器,但是它不能和CMS配合使用,它適合于比較大新生代的情況,此收集器起始于jdk 1.4.0。它比

21、較適合于對(duì)吞吐量高于暫停時(shí)間的場(chǎng)合,Serial gc和Parallel gc可以用如下的圖來(lái)表示:2.3.3 Concurrent CollectorConcurrent Collector通過(guò)并行的方式進(jìn)行垃圾收集,這樣就減少了垃圾收集器收集一次的時(shí)間,這種GC在實(shí)時(shí)性要求高于吞吐量的時(shí)候比較有用。此種GC可以用參數(shù)-XX:UseConcMarkSweepGC配置,此GC主要用于老生代和Perm代的收集?!揪庉嬐扑]】1. Java的未來(lái):百家爭(zhēng)鳴的JVM2. 有關(guān)JVM處理Java數(shù)組方法的思考3. JVM分代垃圾回收策略的基礎(chǔ)概念4. JVM概念之Java對(duì)象的大小與引用類型5. JVM

22、基礎(chǔ)概念總結(jié):數(shù)據(jù)類型、堆與棧this.memoryLimit = (long)(jobConf.getLong(MRJobConfig.REDUCE_MEMORY_TOTAL_BYTES, Math.min(Runtime.getRuntime().maxMemory(), Integer.MAX_VALUE) * maxInMemCopyUse);maxMemory()這個(gè)方法返回的是java虛擬機(jī)(這個(gè)進(jìn)程)能構(gòu)從操作系統(tǒng)那里挖到的最大的內(nèi)存,以字節(jié)為單位.totalMemory()這個(gè)方法返回的是java虛擬機(jī)現(xiàn)在已經(jīng)從操作系統(tǒng)那里挖過(guò)來(lái)的內(nèi)存大小,也就是java虛擬機(jī)這個(gè)進(jìn)程當(dāng)時(shí)所占

23、用的所有內(nèi)存。freeMemory為當(dāng)前jvm中沒(méi)有使用的內(nèi)存。JVM基礎(chǔ):JVM參數(shù)設(shè)置、分析央邦0首付,低押金先就業(yè)后付款上海央邦學(xué)一送一,超值!50000年薪起,頂級(jí)4G手機(jī)開(kāi)發(fā)!【安博亞威】CCIE考試通過(guò)率第一!大數(shù)據(jù)與互聯(lián)網(wǎng)技術(shù)峰會(huì)免費(fèi)注冊(cè)java培訓(xùn)到達(dá)內(nèi),行業(yè)領(lǐng)先品牌中國(guó)IT實(shí)驗(yàn)室收集整理 佚名 2012-2-25 9:18:41 保存本文 推薦給好友 收藏本頁(yè)歡迎進(jìn)入Java社區(qū)論壇,與200萬(wàn)技術(shù)人員互動(dòng)交流 >>進(jìn)入?yún)?shù)名稱含義默認(rèn)值 -Xms初始堆大小物理內(nèi)存的1/64(<1GB)默認(rèn)(Min

24、HeapFreeRatio參數(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è)堆

25、的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ú)限生成

26、,經(jīng)驗(yàn)值在30005000左右一般小的應(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:ThreadStackSizeThread Stack Size (0 means use default stack size) Sparc: 512; Solaris x86:

27、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/5Xms=Xmx并且設(shè)置了Xmn的情況下,該參數(shù)不需要進(jìn)行設(shè)置。-XX:SurvivorRatioEden區(qū)與Survivor區(qū)的大小比值 設(shè)置為8,則兩個(gè)

28、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)用,可以提高效率.如果

29、將此值設(shè)置為一個(gè)較大值,則年輕代對(duì)象會(huì)在Survivor區(qū)進(jìn)行多次復(fù)制,這樣可以增加對(duì)象再年輕代的存活 時(shí)間,增加在年輕代即被回收的概率該參數(shù)只有在串行GC時(shí)才有效.-XX:+AggressiveOpts加快編譯  -XX:+UseBiasedLocking鎖機(jī)制的性能改善  -Xnoclassgc禁用垃圾回收  -XX:SoftRefLRUPolicyMSPerMB每兆堆空閑空間中SoftReference的存活時(shí)間1ssoftly reachable objects will remain alive for some amoun

30、t 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:TLABWasteTargetPercentTLAB占eden區(qū)的百分比1% -XX:+CollectGen0Fi

31、rstFullGC時(shí)是否先YGCfalse 并行收集器相關(guān)參數(shù)-XX:+UseParallelGCFull GC采用parallel MSC(此項(xiàng)待驗(yàn)證) 選擇垃圾收集器為并行收集器.此配置僅對(duì)年輕代有效.即上述配置下,年輕代使用并發(fā)收集,而年老代仍舊使用串行收集.(此項(xiàng)待驗(yàn)證)-XX:+UseParNewGC設(shè)置年輕代為并行收集 可與CMS收集同時(shí)使用JDK5.0以上,JVM會(huì)根據(jù)系統(tǒng)配置自行設(shè)置,所以無(wú)需再設(shè)置此值-XX:ParallelGCThreads并行收集器的線程數(shù) 此值最好配置與處理器數(shù)目相等 同樣適用于CMS-XX:+UseParalle

32、lOldGC年老代垃圾收集方式為并行收集(Parallel Compacting) 這個(gè)是JAVA 6出現(xiàn)的參數(shù)選項(xiàng)-XX:MaxGCPauseMillis每次年輕代垃圾回收的最長(zhǎng)時(shí)間(最大暫停時(shí)間) 如果無(wú)法滿足此時(shí)間,JVM會(huì)自動(dòng)調(diào)整年輕代大小,以滿足此值.-XX:+UseAdaptiveSizePolicy自動(dòng)選擇年輕代區(qū)大小和相應(yīng)的Survivor區(qū)比例 設(shè)置此選項(xiàng)后,并行收集器會(huì)自動(dòng)選擇年輕代區(qū)大小和相應(yīng)的Survivor區(qū)比例,以達(dá)到目標(biāo)系統(tǒng)規(guī)定的最低相應(yīng)時(shí)間或者收集頻率等,此值建議使用并行收集器時(shí),一直打開(kāi).-XX:GCTimeRatio設(shè)置垃圾回收

33、時(shí)間占程序運(yùn)行時(shí)間的百分比 公式為1/(1+n)-XX:+ScavengeBeforeFullGCFull GC前調(diào)用YGCtrueDo young generation GC prior to a full GC. (Introduced in 1.4.1.)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ì)算資源

34、(內(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)

35、內(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ì)算公式-X

36、X:CMSInitiatingPermOccupancyFraction設(shè)置Perm Gen使用到達(dá)多少比率時(shí)觸發(fā)92 -XX:+CMSIncrementalMode設(shè)置為增量模式 用于單CPU情況-XX:+CMSClassUnloadingEnabled   輔助信息-XX:+PrintGC  輸出形式:GC 118250K->113543K(130112K), 0.0094143 secsFull GC 121376K->10414K(130112K), 0.0650971 secs-XX:+PrintGCD

37、etails  輸出形式:GC DefNew: 8614K->781K(9088K), 0.0123035 secs 118250K->113543K(130112K), 0.0124633 secsGC DefNew: 8614K->8614K(9088K), 0.0000665 secsTenured: 112761K->10414K(121024K), 0.0433488 secs 121376K->10414K(130112K), 0.0436268 secs-XX:+PrintGCTimeStamps   

38、;-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:+PrintGCApplicat

39、ionConcurrentTime打印每次垃圾回收前,程序未中斷的執(zhí)行時(shí)間.可與上面混合使用 輸出形式:Application time: 0.5291524 seconds-XX:+PrintHeapAtGC打印GC前后的詳細(xì)堆棧信息  -Xloggc:filename把相關(guān)日志信息記錄到文件以便分析.與上面幾個(gè)配合使用  -XX:+PrintClassHistogramgarbage collects before printing the histogram.  -XX:+PrintTLAB查看TLAB空間的使用情況&

40、#160; XX:+PrintTenuringDistribution查看每次minor GC后新的存活周期的閾值 Desired survivor size 1048576 bytes, new threshold 7 (max 15)new threshold 7即標(biāo)識(shí)新的存活周期的閾值為7。GC性能方面的考慮    對(duì)于GC的性能主要有2個(gè)方面的指標(biāo):吞吐量throughput(工作時(shí)間不算gc的時(shí)間占總的時(shí)間比)和暫停pause(gc發(fā)生時(shí)app對(duì)外顯示的無(wú)法響應(yīng))。    1. Total Heap

41、60;   默認(rèn)情況下,vm會(huì)增加/減少heap大小以維持free space在整個(gè)vm中占的比例,這個(gè)比例由MinHeapFreeRatio和MaxHeapFreeRatio指定。    一般而言,server端的app會(huì)有以下規(guī)則:      對(duì)vm分配盡可能多的memory;    將Xms和Xmx設(shè)為一樣的值。如果虛擬機(jī)啟動(dòng)時(shí)設(shè)置使用的內(nèi)存比較小,這個(gè)時(shí)候又需要初始化很多對(duì)象,虛擬機(jī)就必須重復(fù)地增加內(nèi)存。    處理器核數(shù)增加,內(nèi)存也跟著

42、增大。    2. The Young Generation    另外一個(gè)對(duì)于app流暢性運(yùn)行影響的因素是young generation的大小。young generation越大,minor collection越少;但是在固定heap size情況下,更大的young generation就意味著小的tenured generation,就意味著更多的major collection(major collection會(huì)引發(fā)minor collection)。    NewRatio反映的是youn

43、g和tenured generation的大小比例。NewSize和MaxNewSize反映的是young generation大小的下限和上限,將這兩個(gè)值設(shè)為一樣就固定了young generation的大?。ㄍ琗ms和Xmx設(shè)為一樣)。    如果希望,SurvivorRatio也可以優(yōu)化survivor的大小,不過(guò)這對(duì)于性能的影響不是很大。SurvivorRatio是eden和survior大小比例。    一般而言,server端的app會(huì)有以下規(guī)則:    首先決定能分配給vm的最大的heap

44、size,然后設(shè)定最佳的young generation的大?。?#160;   如果heap size固定后,增加young generation的大小意味著減小tenured generation大小。讓tenured generation在任何時(shí)候夠大,能夠容納所有l(wèi)ive的data(留10%-20%的空余)。    經(jīng)驗(yàn)&&規(guī)則    年輕代大小選擇 ?響應(yīng)時(shí)間優(yōu)先的應(yīng)用:盡可能設(shè)大,直到接近系統(tǒng)的最低響應(yīng)時(shí)間限制(根據(jù)實(shí)際情況選擇)。在此種情況下,年輕代收集發(fā)生的頻率也是最小的。同時(shí),減少

45、到達(dá)年老代的對(duì)象。    吞吐量?jī)?yōu)先的應(yīng)用:盡可能的設(shè)置大,可能到達(dá)Gbit的程度。因?yàn)閷?duì)響應(yīng)時(shí)間沒(méi)有要求,垃圾收集可以并行進(jìn)行,一般適合8CPU以上的應(yīng)用。    避免設(shè)置過(guò)小。當(dāng)新生代設(shè)置過(guò)小時(shí)會(huì)導(dǎo)致:1.YGC次數(shù)更加頻繁 2.可能導(dǎo)致YGC對(duì)象直接進(jìn)入舊生代,如果此時(shí)舊生代滿了,會(huì)觸發(fā)FGC.    年老代大小選擇 ?響應(yīng)時(shí)間優(yōu)先的應(yīng)用:年老代使用并發(fā)收集器,所以其大小需要小心設(shè)置,一般要考慮并發(fā)會(huì)話率和會(huì)話持續(xù)時(shí)間等一些參數(shù)。如果堆設(shè)置小了,可以會(huì)造成內(nèi)存碎 片,高回收頻率以及應(yīng)用暫停而使用傳統(tǒng)

46、的標(biāo)記清除方式;如果堆大了,則需要較長(zhǎng)的收集時(shí)間。最優(yōu)化的方案,一般需要參考以下數(shù)據(jù)獲得:    并發(fā)垃圾收集信息、持久代并發(fā)收集次數(shù)、傳統(tǒng)GC信息、花在年輕代和年老代回收上的時(shí)間比例。    吞吐量?jī)?yōu)先的應(yīng)用:一般吞吐量?jī)?yōu)先的應(yīng)用都有一個(gè)很大的年輕代和一個(gè)較小的年老代。原因是,這樣可以盡可能回收掉大部分短期對(duì)象,減少中期的對(duì)象,而年老代盡存放長(zhǎng)期存活對(duì)象。    較小堆引起的碎片問(wèn)題    因?yàn)槟昀洗牟l(fā)收集器使用標(biāo)記,清除算法,所以不會(huì)對(duì)堆進(jìn)行壓縮。當(dāng)收集器回收時(shí),他會(huì)

47、把相鄰的空間進(jìn)行合并,這樣可以分配給較大的對(duì)象。但是,當(dāng)堆空間較小時(shí),運(yùn)行一段時(shí)間以后,就會(huì)出現(xiàn)"碎片",如果并發(fā)收集器找不到足夠的空間,那么并發(fā)收集器將會(huì)停止,然后使用傳統(tǒng)的標(biāo)記,清除方式進(jìn)行回收。如果出現(xiàn)"碎片",可能需要進(jìn)行如下配置:    -XX:+UseCMSCompactAtFullCollection:使用并發(fā)收集器時(shí),開(kāi)啟對(duì)年老代的壓縮。    -XX:CMSFullGCsBeforeCompaction=0:上面配置開(kāi)啟的情況下,這里設(shè)置多少次Full GC后,對(duì)年老代進(jìn)行壓縮

48、    用64位操作系統(tǒng),Linux下64位的jdk比32位jdk要慢一些,但是吃得內(nèi)存更多,吞吐量更大    XMX和XMS設(shè)置一樣大,MaxPermSize和MinPermSize設(shè)置一樣大,這樣可以減輕伸縮堆大小帶來(lái)的壓力    使用CMS的好處是用盡量少的新生代,經(jīng)驗(yàn)值是128M256M, 然后老生代利用CMS并行收集, 這樣能保證系統(tǒng)低延遲的吞吐效率。 實(shí)際上cms的收集停頓時(shí)間非常的短,2G的內(nèi)存, 大約2080ms的應(yīng)用程序停頓時(shí)間    系統(tǒng)停頓的時(shí)候可能是G

49、C的問(wèn)題也可能是程序的問(wèn)題,多用jmap和jstack查看,或者killall -3 java,然后查看java控制臺(tái)日志,能看出很多問(wèn)題。(相關(guān)工具的使用方法將在后面的blog中介紹)    仔細(xì)了解自己的應(yīng)用,如果用了緩存,那么年老代應(yīng)該大一些,緩存的HashMap不應(yīng)該無(wú)限制長(zhǎng),建議采用LRU算法的Map做緩存,LRUMap的最大長(zhǎng)度也要根據(jù)實(shí)際情況設(shè)定。    采用并發(fā)回收時(shí),年輕代小一點(diǎn),年老代要大,因?yàn)槟昀洗笥玫氖遣l(fā)回收,即使時(shí)間長(zhǎng)點(diǎn)也不會(huì)影響其他程序繼續(xù)運(yùn)行,網(wǎng)站不會(huì)停頓    JVM參數(shù)

50、的設(shè)置(特別是 Xmx Xms Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold等參數(shù)的設(shè)置沒(méi)有一個(gè)固定的公式,需要根據(jù)PV old區(qū)實(shí)際數(shù)據(jù) YGC次數(shù)等多方面來(lái)衡量。為了避免promotion faild可能會(huì)導(dǎo)致xmn設(shè)置偏小,也意味著YGC的次數(shù)會(huì)增多,處理并發(fā)訪問(wèn)的能力下降等問(wèn)題。每個(gè)參數(shù)的調(diào)整都需要經(jīng)過(guò)詳細(xì)的性能測(cè)試,才能找到特定應(yīng)用的最佳配置。    promotion failed:    垃圾回收時(shí)promotion failed是個(gè)很頭痛的問(wèn)題,一般可能是兩種原因產(chǎn)生,第

51、一個(gè)原因是救助空間不夠,救助空間里的對(duì)象還不應(yīng)該被移動(dòng)到年老代,但年輕代又有很多對(duì)象需要放入救助空間;第二個(gè)原因是年老代沒(méi)有足夠的空間接納來(lái)自年輕代的對(duì)象;這兩種情況都會(huì)轉(zhuǎn)向Full GC,網(wǎng)站停頓時(shí)間較長(zhǎng)。    解決方方案一:    第一個(gè)原因我的最終解決辦法是去掉救助空間,設(shè)置-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0即可,第二個(gè)原因我的解決辦法是設(shè)置CMSInitiatingOccupancyFraction為某個(gè)值(假設(shè)70),這樣年老代空間到70%時(shí)就開(kāi)始執(zhí)行CMS

52、,年老代有足夠的空間接納來(lái)自年輕代的對(duì)象。    解決方案一的改進(jìn)方案:    又有改進(jìn)了,上面方法不太好,因?yàn)闆](méi)有用到救助空間,所以年老代容易滿,CMS執(zhí)行會(huì)比較頻繁。我改善了一下,還是用救助空間,但是把救助空間加大,這樣也不會(huì)有promotion failed。具體操作上,32位Linux和64位Linux好像不一樣,64位系統(tǒng)似乎只要配置MaxTenuringThreshold參數(shù),CMS還是有暫停。為了解決暫停問(wèn)題和promotion failed問(wèn)題,最后我設(shè)置-XX:SurvivorRatio=1 ,并把MaxTenuringThreshold去掉,這樣即沒(méi)有暫停又不會(huì)有promotoin failed,而且更重要的是,年老代和永久代上升非常慢(因?yàn)楹枚鄬?duì)象到不了年老代就被回收了),所以CMS執(zhí)行頻率非常低,好幾個(gè)小時(shí)才執(zhí)行一次,這樣,服務(wù)器都不

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論