JVM的垃圾回收機制詳解和調優

JVM的垃圾回收機制詳解和調優java

gc即垃圾收集機制是指jvm用於釋放那些再也不使用的對象所佔用的內存。java語言並不要求jvm有gc,也沒有規定gc如何工做。不過經常使用的jvm都有gc,並且大多數gc都使用相似的算法管理內存和執行收集操做。算法

1.JVM的gc概述服務器

gc即垃圾收集機制是指jvm用於釋放那些再也不使用的對象所佔用的內存。java語言並不要求jvm有gc,也沒有規定gc如何工做。不過經常使用的jvm都有gc,並且大多數gc都使用相似的算法管理內存和執行收集操做。多線程

在充分理解了垃圾收集算法和執行過程後,纔能有效的優化它的性能。有些垃圾收集專用於特殊的應用程序。好比,實時應用程序主要是爲了不垃圾收集中斷,而大多數OLTP應用程序則注重總體效率。理解了應用程序的工做負荷和jvm支持的垃圾收集算法,即可以進行優化配置垃圾收集器。併發

垃圾收集的目的在於清除再也不使用的對象。gc經過肯定對象是否被活動對象引用來肯定是否收集該對象。gc首先要判斷該對象是不是時候能夠收集。兩種經常使用的方法是引用計數和對象引用遍歷。jvm

1.1.引用計數jsp

引用計數存儲對特定對象的全部引用數,也就是說,當應用程序建立引用以及引用超出範圍時,jvm必須適當增減引用數。當某對象的引用數爲0時,即可以進行垃圾收集。性能

1.2.對象引用遍歷測試

早期的jvm使用引用計數,如今大多數jvm採用對象引用遍歷。對象引用遍歷從一組對象開始,沿着整個對象圖上的每條連接,遞歸肯定可到達(reachable)的對象。若是某對象不能從這些根對象的一個(至少一個)到達,則將它做爲垃圾收集。在對象遍歷階段,gc必須記住哪些對象能夠到達,以便刪除不可到達的對象,這稱爲標記(marking)對象。優化

下一步,gc要刪除不可到達的對象。刪除時,有些gc只是簡單的掃描堆棧,刪除未標記的未標記的對象,並釋放它們的內存以生成新的對象,這叫作清除(sweeping)。這種方法的問題在於內存會分紅好多小段,而它們不足以用於新的對象,可是組合起來卻很大。所以,許多gc能夠從新組織內存中的對象,並進行壓縮(compact),造成可利用的空間。

爲此,gc須要中止其餘的活動活動。這種方法意味着全部與應用程序相關的工做中止,只有gc運行。結果,在響應期間增減了許多混雜請求。另外,更復雜的gc不斷增長或同時運行以減小或者清除應用程序的中斷。有的gc使用單線程完成這項工做,有的則採用多線程以增長效率。

2.幾種垃圾回收機制

2.1.標記-清除收集器

這種收集器首先遍歷對象圖並標記可到達的對象,而後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器通常使用單線程工做並中止其餘操做。

2.2.標記-壓縮收集器

有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象複製到堆棧的新域中以便壓縮堆棧。這種收集器也中止其餘操做。

2.3.複製收集器

這種收集器將堆棧分爲兩個域,常稱爲半空間。每次僅使用一半的空間,jvm生成的新對象則放在另外一半空間中。gc運行時,它把可到達對象複製到另外一半空間,從而壓縮了堆棧。這種方法適用於短生存期的對象,持續複製長生存期的對象則致使效率下降。

2.4.增量收集器

增量收集器把堆棧分爲多個域,每次僅從一個域收集垃圾。這會形成較小的應用程序中斷。

2.5.分代收集器

這種收集器把堆棧分爲兩個或多個域,用以存放不一樣壽命的對象。jvm生成的新對象通常放在其中的某個域中。過一段時間,繼續存在的對象將得到使用期並轉入更長壽命的域中。分代收集器對不一樣的域使用不一樣的算法以優化性能。

2.6.併發收集器

併發收集器與應用程序同時運行。這些收集器在某點上(好比壓縮時)通常都不得不中止其餘操做以完成特定的任務,可是由於其餘應用程序可進行其餘的後臺操做,因此中斷其餘處理的實際時間大大下降。

2.7.並行收集器

並行收集器使用某種傳統的算法並使用多線程並行的執行它們的工做。在多cpu機器上使用多線程技術能夠顯著的提升java應用程序的可擴展性。

3.Sun HotSpot 1.4.1 JVM堆大小的調整

Sun HotSpot 1.4.1使用分代收集器,它把堆分爲三個主要的域:新域、舊域以及永久域。Jvm生成的全部新對象放在新域中。一旦對象經歷了必定數量的垃圾收集循環後,便得到使用期並進入舊域。在永久域中jvm則存儲class和method對象。就配置而言,永久域是一個獨立域而且不認爲是堆的一部分。

下面介紹如何控制這些域的大小。可以使用-Xms和-Xmx 控制整個堆的原始大小或最大值。

下面的命令是把初始大小設置爲128M:

java –Xms128m

–Xmx256m爲控制新域的大小,可以使用-XX:NewRatio設置新域在堆中所佔的比例。

下面的命令把整個堆設置成128m,新域比率設置成3,即新域與舊域比例爲1:3,新域爲堆的1/4或32M:

java –Xms128m –Xmx128m–XX:NewRatio =3可以使用-XX:NewSize和-XX:MaxNewsize設置新域的初始值和最大值。

下面的命令把新域的初始值和最大值設置成64m:

java –Xms256m –Xmx256m –Xmn64m

永久域默認大小爲4m.運行程序時,jvm會調整永久域的大小以知足須要。每次調整時,jvm會對堆進行一次徹底的垃圾收集。

使用-XX:MaxPerSize標誌來增長永久域搭大小。在WebLogic Server應用程序加載較多類時,常常須要增長永久域的最大值。當jvm加載類時,永久域中的對象急劇增長,從而使jvm不斷調整永久域大小。爲了不調整,可以使用-XX:PerSize標誌設置初始值。

下面把永久域初始值設置成32m,最大值設置成64m.

java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m

默認狀態下,HotSpot在新域中使用複製收集器。該域通常分爲三個部分。第一部分爲Eden,用於生成新的對象。另兩部分稱爲救助空間,當Eden充滿時,收集器中止應用程序,把全部可到達對象複製到當前的from救助空間,一旦當前的from救助空間充滿,收集器則把可到達對象複製到當前的to救助空間。From和to救助空間互換角色。維持活動的對象將在救助空間不斷複製,直到它們得到使用期並轉入舊域。使用-XX:SurvivorRatio可控制新域子空間的大小。

同NewRation同樣,SurvivorRation規定某救助域與Eden空間的比值。好比,如下命令把新域設置成64m,Eden佔32m,每一個救助域各佔16m:

java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2

如前所述,默認狀態下HotSpot對新域使用複製收集器,對舊域使用標記-清除-壓縮收集器。在新域中使用複製收集器有不少意義,由於應用程序生成的大部分對象是短壽命的。理想狀態下,全部過渡對象在移出Eden空間時將被收集。若是可以這樣的話,而且移出Eden空間的對象是長壽命的,那麼理論上能夠當即把它們移進舊域,避免在救助空間反覆複製。可是,應用程序不能適合這種理想狀態,由於它們有一小部分中長壽命的對象。最好是保持這些中長壽命的對象並放在新域中,由於複製小部分的對象總比壓縮舊域廉價。爲控制新域中對象的複製,可用-XX:TargetSurvivorRatio控制救助空間的比例(該值是設置救助空間的使用比例。如救助空間位1M,該值50表示可用500K)。該值是一個百分比,默認值是50.當較大的堆棧使用較低的sruvivorratio時,應增長該值到80至90,以更好利用救助空間。用-XX:maxtenuring threshold可控制上限。

爲放置全部的複製所有發生以及但願對象從eden擴展到舊域,能夠把MaxTenuring Threshold設置成0.設置完成後,實際上就再也不使用救助空間了,所以應把SurvivorRatio設成最大值以最大化Eden空間,設置以下:

java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …

4.BEA JRockit JVM的使用

Bea WebLogic 8.1使用的新的JVM用於Intel平臺。在Bea安裝完畢的目錄下能夠看到有一個相似於jrockit81sp1_141_03的文件夾。這就是Bea新JVM所在目錄。不一樣於HotSpot把Java字節碼編譯成本地碼,它預先編譯成類。JRockit還提供了更細緻的功能用以觀察JVM的運行狀態,主要是獨立的GUI控制檯(只能適用於使用Jrockit才能使用jrockit81sp1_141_03自帶的console監控一些cpu及memory參數)或者WebLogic Server控制檯。

Bea JRockit JVM支持4種垃圾收集器:

4.1.1.分代複製收集器

它與默認的分代收集器工做策略相似。對象在新域中分配,即JRockit文檔中的nursery.這種收集器最適合單cpu機上小型堆操做。

4.1.2.單空間併發收集器

該收集器使用完整堆,並與背景線程共同工做。儘管這種收集器能夠消除中斷,可是收集器需花費較長的時間尋找死對象,並且處理應用程序時收集器常常運行。若是處理器不能應付應用程序產生的垃圾,它會中斷應用程序並關閉收集。

分代併發收集器 這種收集器在護理域使用排它複製收集器,在舊域中則使用併發收集器。因爲它比單空間共同發生收集器中斷頻繁,所以它須要較少的內存,應用程序的運行效率也較高,注意,太小的護理域能夠致使大量的臨時對象被擴展到舊域中。這會形成收集器超負荷運做,甚至採用排它性工做方式完成收集。

4.1.3.並行收集器

該收集器也中止其餘進程的工做,但使用多線程以加速收集進程。儘管它比其餘的收集器易於引發長時間的中斷,但通常能更好的利用內存,程序效率也較高。

默認狀態下,JRockit使用分代併發收集器。要改變收集器,可以使用-Xgc:<gc_name>,對應四個收集器分別爲gencopy,singlecon,gencon以及parallel.可以使用-Xms和-Xmx設置堆的初始大小和最大值。要設置護理域,則使用-Xns:java –jrockit –Xms512m –Xmx512m –Xgc:gencon –Xns128m…儘管JRockit支持-verbose:gc開關,但它輸出的信息會因收集器的不一樣而異。JRockit還支持memory、load和codegen的輸出。

注意 :若是 使用JRockit JVM的話還可使用WLS自帶的console(C:\bea\jrockit81sp1_141_03\bin下)來監控一些數據,如cpu,memery等。要想能構監控必須在啓動服務時startWeblogic.cmd中加入-Xmanagement參數。

5.如何從JVM中獲取信息來進行調整

-verbose.gc開關可顯示gc的操做內容。打開它,能夠顯示最忙和最空閒收集行爲發生的時間、收集先後的內存大小、收集須要的時間等。打開-xx:+ printgcdetails開關,能夠詳細瞭解gc中的變化。打開-XX: + PrintGCTimeStamps開關,能夠了解這些垃圾收集發生的時間,自jvm啓動之後以秒計量。最後,經過-xx: + PrintHeapAtGC開關了解堆的更詳細的信息。爲了瞭解新域的狀況,能夠經過-XX:=PrintTenuringDistribution開關了解得到使用期的對象權。

6.Pdm系統JVM調整

6.1.服務器:前提內存1G 單CPU

可經過以下參數進行調整:-server 啓用服務器模式(若是CPU多,服務器機建議使用此項)

-Xms,-Xmx通常設爲一樣大小。 800m

-Xmn 是將NewSize與MaxNewSize設爲一致。320m

-XX:PerSize 64m

-XX:NewSize 320m 此值設大可調大新對象區,減小Full GC次數

-XX:MaxNewSize 320m

-XX:NewRato NewSize設了可不設。4

-XX: SurvivorRatio 4

-XX:userParNewGC 可用來設置並行收集

-XX:ParallelGCThreads 可用來增長並行度 4

-XXUseParallelGC 設置後可使用並行清除收集器

-XX:UseAdaptiveSizePolicy 與上面一個聯合使用效果更好,利用它能夠自動優化新域大小以及救助空間比值

6.2.客戶機:經過在JNLP文件中設置參數來調整客戶端JVM

JNLP中參數:initial-heap-size和max-heap-size

這能夠在framework的RequestManager中生成JNLP文件時加入上述參數,可是這些值是要求根據客戶機的硬件狀態變化的(如客戶機的內存大小等)。建議這兩個參數值設爲客戶機可用內存的60%(有待測試)。爲了在動態生成JNLP時以上兩個參數值可以隨客戶機不一樣而不一樣,可靠慮得到客戶機系統信息並將這些嵌到首頁index.jsp中做爲鏈接請求的參數。

在設置了上述參數後能夠經過Visualgc 來觀察垃圾回收的一些參數狀態,再作相應的調整來改善性能。通常的標準是減小fullgc的次數,最好硬件支持使用並行垃圾回收(要求多CPU)。

相關文章
相關標籤/搜索