熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

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

2022-06-13   來源: Java核心技術 

  JVM的gc概述
  
  gc即垃圾收集機制是指jvm用於釋放那些不再使用的對象所占用的內存java語言並不要求jvm有gc也沒有規定gc如何工作不過常用的jvm都有gc而且大多數gc都使用類似的算法管理內存和執行收集操作
  
  在充分理解了垃圾收集算法和執行過程後才能有效的優化它的性能有些垃圾收集專用於特殊的應用程序比如實時應用程序主要是為了避免垃圾收集中斷而大多數OLTP應用程序則注重整體效率理解了應用程序的工作負荷和jvm支持的垃圾收集算法便可以進行優化配置垃圾收集器
  
  垃圾收集的目的在於清除不再使用的對象gc通過確定對象是否被活動對象引用來確定是否收集該對象gc首先要判斷該對象是否是時候可以收集兩種常用的方法是引用計數和對象引用遍歷
  
  引用計數
  
  引用計數存儲對特定對象的所有引用數也就是說當應用程序創建引用以及引用超出范圍時jvm必須適當增減引用數當某對象的引用數為便可以進行垃圾收集
  
  對象引用遍歷
  
  早期的jvm使用引用計數現在大多數jvm采用對象引用遍歷對象引用遍歷從一組對象開始沿著整個對象圖上的每條鏈接遞歸確定可到達(reachable)的對象如果某對象不能從這些根對象的一個(至少一個)到達則將它作為垃圾收集在對象遍歷階段gc必須記住哪些對象可以到達以便刪除不可到達的對象這稱為標記(marking)對象
  
  下一步gc要刪除不可到達的對象刪除時有些gc只是簡單的掃描堆棧刪除未標記的未標記的對象並釋放它們的內存以生成新的對象這叫做清除(sweeping)這種方法的問題在於內存會分成好多小段而它們不足以用於新的對象但是組合起來卻很大因此許多gc可以重新組織內存中的對象並進行壓縮(compact)形成可利用的空間
  
  為此gc需要停止其他的活動活動這種方法意味著所有與應用程序相關的工作停止只有gc運行結果在響應期間增減了許多混雜請求另外更復雜的 gc不斷增加或同時運行以減少或者清除應用程序的中斷有的gc使用單線程完成這項工作有的則采用多線程以增加效率
  
  幾種垃圾回收機制
  
  標記-清除收集器
  
  這種收集器首先遍歷對象圖並標記可到達的對象然後掃描堆棧以尋找未標記對象並釋放它們的內存這種收集器一般使用單線程工作並停止其他操作
  
  標記-壓縮收集器
  
  有時也叫標記-清除-壓縮收集器與標記-清除收集器有相同的標記階段在第二階段則把標記對象復制到堆棧的新域中以便壓縮堆棧這種收集器也停止其他操作
  
  復制收集器
  
  這種收集器將堆棧分為兩個域常稱為半空間每次僅使用一半的空間jvm生成的新對象則放在另一半空間中gc運行時它把可到達對象復制到另一半空間從而壓縮了堆棧這種方法適用於短生存期的對象持續復制長生存期的對象則導致效率降低
  
  增量收集器
  
  增量收集器把堆棧分為多個域每次僅從一個域收集垃圾這會造成較小的應用程序中斷
  
  分代收集器
  
  這種收集器把堆棧分為兩個或多個域用以存放不同壽命的對象jvm生成的新對象一般放在其中的某個域中過一段時間繼續存在的對象將獲得使用期並轉入更長壽命的域中分代收集器對不同的域使用不同的算法以優化性能
  
  並發收集器
  
  並發收集器與應用程序同時運行這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務但是因為其他應用程序可進行其他的後台操作所以中斷其他處理的實際時間大大降低
  
  並行收集器
  
  並行收集器使用某種傳統的算法並使用多線程並行的執行它們的工作在多cpu機器上使用多線程技術可以顯著的提高java應用程序的可擴展性
  
  Sun HotSpot
  
   JVM堆大小的調整
  
  Sun HotSpot 使用分代收集器它把堆分為三個主要的域新域舊域以及永久域Jvm生成的所有新對象放在新域中一旦對象經歷了一定數量的垃圾收集循環後便獲得使用期並進入舊域在永久域中jvm則存儲class和method對象就配置而言永久域是一個獨立域並且不認為是堆的一部分
  
  下面介紹如何控制這些域的大小可使用Xms和Xmx 控制整個堆的原始大小或最大值
  
  下面的命令是把初始大小設置為M
  
  java –Xmsm
  
  –Xmxm為控制新域的大小可使用XX:NewRatio設置新域在堆中所占的比例
  
  下面的命令把整個堆設置成m新域比率設置成即新域與舊域比例為新域為堆的/M
  
  java –Xmsm –Xmxm
  –XX:NewRatio =可使用XX:NewSize和XX:MaxNewsize設置新域的初始值和最大值
  
  下面的命令把新域的初始值和最大值設置成m:
  
  java –Xmsm –Xmxm –Xmnm
  
  永久域默認大小為m運行程序時jvm會調整永久域的大小以滿足需要每次調整時jvm會對堆進行一次完全的垃圾收集
  
  使用XX:MaxPerSize標志來增加永久域搭大小在WebLogic Server應用程序加載較多類時經常需要增加永久域的最大值當jvm加載類時永久域中的對象急劇增加從而使jvm不斷調整永久域大小為了避免調整可使用XX:PerSize標志設置初始值
  
  下面把永久域初始值設置成m最大值設置成m
  
  java Xmsm Xmxm Xmnm XX:PermSize=m XX:MaxPermSize=m
  
  默認狀態下HotSpot在新域中使用復制收集器該域一般分為三個部分第一部分為Eden用於生成新的對象另兩部分稱為救助空間當Eden 充滿時收集器停止應用程序把所有可到達對象復制到當前的from救助空間一旦當前的from救助空間充滿收集器則把可到達對象復制到當前的to救助空間From和to救助空間互換角色維持活動的對象將在救助空間不斷復制直到它們獲得使用期並轉入舊域使用XX:SurvivorRatio 可控制新域子空間的大小
  
  同NewRation一樣SurvivorRation規定某救助域與Eden空間的比值比如以下命令把新域設置成mEden占m每個救助域各占m
  
  java Xmsm Xmxm Xmnm XX:SurvivorRation =
  
  如前所述默認狀態下HotSpot對新域使用復制收集器對舊域使用標記-清除-壓縮收集器在新域中使用復制收集器有很多意義因為應用程序生成的大部分對象是短壽命的理想狀態下所有過渡對象在移出Eden空間時將被收集如果能夠這樣的話並且移出Eden空間的對象是長壽命的那麼理論上可以立即把它們移進舊域避免在救助空間反復復制但是應用程序不能適合這種理想狀態因為它們有一小部分中長壽命的對象最好是保持這些中長壽命的對象並放在新域中因為復制小部分的對象總比壓縮舊域廉價為控制新域中對象的復制可用XX:TargetSurvivorRatio控制救助空間的比例(該值是設置救助空間的使用比例如救助空間位M該值表示可用K)該值是一個百分比默認值是當較大的堆棧使用較低的 sruvivorratio時應增加該值到以更好利用救助空間XX:maxtenuring threshold可控制上限
  
  為放置所有的復制全部發生以及希望對象從eden擴展到舊域可以把MaxTenuring Threshold設置成設置完成後實際上就不再使用救助空間了因此應把SurvivorRatio設成最大值以最大化Eden空間設置如下
  
  java … XX:MaxTenuringThreshold= –XX:SurvivorRatio=
  
  BEA JRockit JVM的使用
  
  Bea WebLogic 使用的新的JVM用於Intel平台在Bea安裝完畢的目錄下可以看到有一個類似於jrockitsp__的文件夾這就是 Bea新JVM所在目錄不同於HotSpot把Java字節碼編譯成本地碼它預先編譯成類JRockit還提供了更細致的功能用以觀察JVM的運行狀態主要是獨立的GUI控制台(只能適用於使用Jrockit才能使用jrockitsp__自帶的console監控一些cpu及 memory參數)或者WebLogic Server控制台
  
  Bea JRockit JVM支持種垃圾收集器
  
  分代復制收集器
  
  它與默認的分代收集器工作策略類似對象在新域中分配即JRockit文檔中的nursery這種收集器最適合單cpu機上小型堆操作
  
  單空間並發收集器
  
  該收集器使用完整堆並與背景線程共同工作盡管這種收集器可以消除中斷但是收集器需花費較長的時間尋找死對象而且處理應用程序時收集器經常運行如果處理器不能應付應用程序產生的垃圾它會中斷應用程序並關閉收集
  
  分代並發收集器這種收集器在護理域使用排它復制收集器在舊域中則使用並發收集器由於它比單空間共同發生收集器中斷頻繁因此它需要較少的內存應用程序的運行效率也較高注意過小的護理域可以導致大量的臨時對象被擴展到舊域中這會造成收集器超負荷運作甚至采用排它性工作方式完成收集
  
   From:http://tw.wingwit.com/Article/program/Java/hx/201311/26281.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.