Java的記憶體回收機制詳解和調優大全

來源:互聯網
上載者:User
gc即垃圾收集機制是指JVM用於釋放那些不再使用的對象所佔用的記憶體。Java語言並不要求JVM有gc,也沒有規定gc如何工作。不過常用的JVM都有gc,而且大多數gc都使用類似的演算法管理記憶體和執行收集操作。 

在充分理解了垃圾收集演算法和執行過程後,才能有效最佳化它的效能。有些垃圾收集專用於特殊的應用程式。比如,即時應用程式主要是為了避免垃圾收集中斷,而大多數OLTP應用程式則注重整體效率。理解了應用程式的工作負載和JVM支援的垃圾收集演算法,便可以進行最佳化配置垃圾收集器。 

垃圾收集的目的在於清除不再使用的對象。gc通過確定對象是否被使用中的物件引用來確定是否收集該對象。gc首先要判斷該對象是否是時候可以收集。兩種常用的方法是引用計數和對象引用遍曆。 

1.1.引用計數 

引用計數儲存對特定對象的所有引用數,也就是說,當應用程式建立引用以及引用超出範圍時,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應用程式的可擴充性。 

 


Java的記憶體回收機制詳解和調優大全 (2)
木頭 轉貼   更新:2005-12-12 15:55:27  版本: 1.0   

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空間,設定如下: 

http://tech.ccidnet.com/art/1112/20051025/357575_3.html

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.