深入JVM系列(二)之GC機制、收集器與GC調優


一、回想JVM內存分配


須要了解很多其它內存模式與內存分配的,請看 深入JVM系列(一)之內存模型與內存分配


1.1、內存分配:

1、對象優先在EDEN分配
2、大對象直接進入老年代 
3、長期存活的對象將進入老年代 
4、適齡對象也可能進入老年代:動態對象年齡推斷



動態對象年齡推斷:

虛擬機並不總是要求對象的年齡必須達到MaxTenuringThreshold才干晉升到老年代,當Survivor空間的同樣年齡的全部對象大小總和大於Survivor空間的一半,年齡大於或等於該年齡的對象就能夠直接進入老年代,無需等到MaxTenuringThreshold中指定的年齡



1.2、總結一下:


1、對象優先在Eden分配。這里大部分對象具有朝生夕滅的特征。Minor GC主要清理該處
2、大對象(占內存大)、老對象(使用頻繁)

3、Survivor無法容納的對象,將進入老年代。Full GC的主要清理該處


二、JVM的GC機制


JVM有2個GC線程


第一個線程負責回收Heap的Young區
第二個線程在Heap不足時,遍歷Heap,將Young 區升級為Older區


Older區的大小等於-Xmx減去-Xmn。不能將-Xms的值設的過大,由於第二個線程被迫執行會降低JVM的性能



2.1、堆內存GC


       JVM(採用分代回收的策略)。用較高的頻率對年輕的對象(young generation)進行YGC,而對老對象(tenured generation)較少(tenured generation 滿了后才進行)進行Full GC。這樣就不須要每次GC都將內存中全部對象都檢查一遍。


2.2、非堆內存不GC


      GC不會在主程序執行期對PermGen Space進行清理。所以假設你的應用中有非常多CLASS(特別是動態生成類。當然permgen space存放的內容不僅限於類)的話,就非常可能出現PermGen Space錯誤。


2.3、內存申請、對象衰老過程


2.3.1、內存申請過程


  1. JVM會試圖為相關Java對象在Eden中初始化一塊內存區域;
  2. 當Eden空間足夠時。內存申請結束。

    否則到下一步;

  3. JVM試圖釋放在Eden中全部不活躍的對象(minor collection)。釋放后若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區。
  4. Survivor區被用來作為Eden及old的中間交換區域,當OLD區空間足夠時。Survivor區的對象會被移到Old區,否則會被保留在Survivor區;
  5. 當old區空間不夠時,JVM會在old區進行major collection;
  6. 全然垃圾收集后,若Survivor及old區仍然無法存放從Eden復制過來的部分對象,導致JVM無法在Eden區為新對象創建內存區域。則出現”Out of memory錯誤”;

2.3.2、對象衰老過程


  1. 新創建的對象的內存都分配自eden。Minor collection的過程就是將eden和在用survivor space中的活對象copy到空暇survivor space中。對象在young generation里經歷了一定次數(能夠通過參數配置)的minor collection后。就會被移到old generation中,稱為tenuring。

GC觸發條件

GC類型 觸發條件 觸發時發生了什么 注意 查看方式
YGC eden空間不足

清空Eden+from survivor中全部no ref的對象占用的內存
將eden+from sur中全部存活的對象copy到to sur中
一些對象將晉升到old中:
    to sur放不下的
    存活次數超過turning threshold中的
又一次計算tenuring threshold(serial parallel GC會觸發此項)

又一次調整Eden 和from的大小(parallel GC會觸發此項)

全過程暫停應用
是否為多線程處理由詳細的GC決定
jstat –gcutil 
gc log
FGC old空間不足
perm空間不足
顯示調用System.GC, RMI等的定時觸發
YGC時的悲觀策略
dump live的內存信息時(jmap –dump:live)
清空heap中no ref的對象
permgen中已經被卸載的classloader中載入的class信息

如配置了CollectGenOFirst,則先觸發YGC(針對serial GC)
如配置了ScavengeBeforeFullGC,則先觸發YGC(針對serial GC)
全過程暫停應用
是否為多線程處理由詳細的GC決定

是否壓縮須要看配置的詳細GC
jstat –gcutil 
gc log



permanent generation空間不足會引發Full GC,仍然不夠會引發PermGen Space錯誤。


三、GC監視、收集器與GC調優


3.1、監視JVM GC


首先說一下怎樣監視JVM GC。能夠用JDK中的jstat工具,也能夠在java程序啟動的opt里加上例如以下幾個參數(注:這兩個參數僅僅針對SUN的HotSpotVM):


  1. -XX:-PrintGCPrintmessagesatgarbagecollection.Manageable.    
  2. -XX:-PrintGCDetailsPrintmoredetailsatgarbagecollection.Manageable.(Introducedin1.4.0.)    
  3. -XX:-PrintGCTimeStampsPrinttimestampsatgarbagecollection.Manageable(Introducedin1.4.0.)   

  1. -XX:-PrintGCPrintmessagesatgarbagecollection.Manageable.    
  2. -XX:-PrintGCDetailsPrintmoredetailsatgarbagecollection.Manageable.(Introducedin1.4.0.)    
  3. -XX:-PrintGCTimeStampsPrinttimestampsatgarbagecollection.Manageable(Introducedin1.4.0.)   
-XX:-PrintGCPrintmessagesatgarbagecollection.Manageable.  
-XX:-PrintGCDetailsPrintmoredetailsatgarbagecollection.Manageable.(Introducedin1.4.0.)  
-XX:-PrintGCTimeStampsPrinttimestampsatgarbagecollection.Manageable(Introducedin1.4.0.) 


當把-XX:-PrintGCDetails添加到javaopt里以后能夠看見例如以下輸出:


[GC[DefNew:34538K->2311K(36352K),0.0232439secs]45898K->15874K(520320K),0.0233874secs]
[FullGC[Tenured:13563K->15402K(483968K),0.2368177secs]21163K->15402K(520320K),[Perm:28671K->28635K(28672K)],0.2371537secs]


他們分別顯示了JVM GC的過程,清理出了多少空間。第一行GC使用的是‘普通GC’(MinorCollections)。第二行使用的是‘全GC’(MajorCollections)。他們的差別非常大。在第一行最后我們能夠看見他的時間是0.0233874秒,而第二行的FullGC的時間是0.2371537秒。第二行的時間是第一行的接近10倍,也就是我們這次調優的重點。降低FullGC的次數。以為FullGC會暫停程序比較長的時間,假設FullGC的次數比較多。

程序就會常常性的假死。

注:

GC信息的格式


[GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs]
<collector> GC為minor收集過程中使用的垃圾收集器起的內部名稱.
<starting occupancy1> young generation 在進行垃圾收集前被對象使用的存儲空間.
<ending occupancy1> young generation 在進行垃圾收集后被對象使用的存儲空間
<pause time1> minor收集使應用暫停的時間長短(秒) 
<starting occupancy3> 整個堆(Heap Size)在進行垃圾收集前被對象使用的存儲空間
<ending occupancy3> 整個堆(Heap Size)在進行垃圾收集后被對象使用的存儲空間
<pause time3> 整個垃圾收集使應用暫停的時間長短(秒),包含major收集使應用暫停的時間(假設發生了major收集).

GC信息的選項


-XX:+PrintGCDetails 顯示GC的詳細信息
-XX:+PrintGCApplicationConcurrentTime 打印應用執行的時間
-XX:+PrintGCApplicationStoppedTime 打印應用被暫停的時間



3.2、collector收集器的種類   

   

GC在 HotSpot VM 5.0里有四種:

incremental (sometimes called train) low pause collector已被廢棄,不在介紹.

類別 serial collector parallel collector
throughput collector )
concurrent collector
(concurrent low pause collector)
介紹 單線程收集器
使用單線程去完畢全部的gc工作,沒有線程間的通信。這樣的方式會相對高效
並行收集器
使用多線程的方式,利用多CUP來提高GC的效率
主要以到達一定的吞吐量為目標
並發收集器
使用多線程的方式,利用多CUP來提高GC的效率
並發完畢大部分工作。使得gc pause短
試用場景 單處理器機器且沒有pause time的要求 適用於科學技術和后台處理
有中規模/大規模數據集大小的應用且執行在多處理器上,關注吞吐量(throughput)
適合中規模/大規模數據集大小的應用。應用服務器,電信領域
關注response time,而不是throughput
使用 Client模式下默認
可使用
可用-XX:+UseSerialGC強制使用
長處:對server應用沒什么長處
缺點:慢,不能充分發揮硬件資源

Server模式下默認

–YGC:PS FGC:Parallel MSC

可用-XX:+UseParallelGC或-XX:+UseParallelOldGC強制指定

–ParallelGC代表FGC為Parallel MSC

–ParallelOldGC代表FGC為Parallel Compacting

長處:高效

缺點:當heap變大后,造成的暫停時間會變得比較長

可用-XX:+UseConcMarkSweepGC強制指定
長處:
對old進行回收時,相應用造成的暫停時間非常端,適合對latency要求比較高的應用
缺點:
1.內存碎片和浮動垃圾
2.old去的內存分配效率低
3.回收的整個耗時比較長
4.和應用爭搶CPU
內存回收觸發 YGC
eden空間不足
FGC
old空間不足
perm空間不足
顯示調用System.gc() ,包含RMI等的定時觸發
YGC時的悲觀策略
dump live的內存信息時(jmap –dump:live)
YGC
eden空間不足
FGC
old空間不足
perm空間不足
顯示調用System.gc() ,包含RMI等的定時觸發
YGC時的悲觀策略–YGC前&YGC后
dump live的內存信息時(jmap –dump:live)
YGC
eden空間不足
CMS GC
1.old Gen的使用率大的一定的比率 默覺得92%
2.配置了CMSClassUnloadingEnabled,且Perm Gen的使用達到一定的比率 默覺得92%
3.Hotspot自己依據預計決定是否要觸法
4.在配置了ExplictGCInvokesConcurrent的情況下顯示調用了System.gc.
Full GC(Serial MSC)
promotion failed 或 concurrent Mode Failure時;
內存回收觸發時發生了什么 YGC
eden空間不足
FGC
old空間不足
perm空間不足
顯示調用System.gc() ,包含RMI等的定時觸發
YGC時的悲觀策略
dump live的內存信息時(jmap –dump:live)
YGC
同serial動作基本同樣,不同點:
1.多線程處理
2.YGC的最后不僅又一次計算Tenuring Threshold,還會又一次調整Eden和From的大小
FGC
1.如配置了ScavengeBeforeFullGC(默認),則先觸發YGC(??)
2.MSC:清空heap中的no ref對象,permgen中已經被卸載的classloader中載入的class信息,並進行壓縮
3.Compacting:清空heap中部分no ref的對象,permgen中已經被卸載的classloader中載入的class信息,並進行部分壓縮
多線程做以上動作.
YGC
同serial動作基本同樣,不同點:
1.多線程處理
CMSGC:
1.old gen到達比率時僅僅清除old gen中no ref的對象所占用的空間
2.perm gen到達比率時僅僅清除已被清除的classloader載入的class信息
FGC
同serial
細節參數 可用-XX:+UseSerialGC強制使用
-XX:SurvivorRatio=x,控制eden/s0/s1的大小
-XX:MaxTenuringThreshold,用於控制對象在新生代存活的最大次數
-XX:PretenureSizeThreshold=x,控制超過多大的字節的對象就在old分配.
-XX:SurvivorRatio=x,控制eden/s0/s1的大小
-XX:MaxTenuringThreshold,用於控制對象在新生代存活的最大次數

-XX:UseAdaptiveSizePolicy 去掉YGC后動態調整eden from已經tenuringthreshold的動作

-XX:ParallelGCThreads 設置並行的線程數

-XX:CMSInitiatingOccupancyFraction 設置old gen使用到達多少比率時觸發
-XX:CMSInitiatingPermOccupancyFraction,設置Perm Gen使用到達多少比率時觸發
-XX:+UseCMSInitiatingOccupancyOnly禁止hostspot自行觸發CMS GC

注:

  • throughput collector與concurrent low pause collector的差別是throughput collector僅僅在young area使用使用多線程,而concurrent low pause collector則在tenured generation也使用多線程。

  • 依據官方文檔,他們倆個須要在多CPU的情況下,才干發揮作用。在一個CPU的情況下,會不如默認的serial collector,由於線程管理須要耗費CPU資源。

    而在兩個CPU的情況下,也提高不大。

    僅僅是在很多其它CPU的情況下。才會有所提高。當然 concurrent low pause collector有一種模式能夠在CPU較少的機器上,提供盡可能少的停頓的模式,見CMS GC Incremental mode

  • 當要使用throughput collector時。在java opt里加上-XX:+UseParallelGC。啟動throughput collector收集。也可加上-XX:ParallelGCThreads=<desired number>來改變線程數。

    還有兩個參數 -XX:MaxGCPauseMillis=<nnn>和 -XX:GCTimeRatio=<nnn>,MaxGCPauseMillis=<nnn>用來控制最大暫停時間,而-XX: GCTimeRatio能夠提高GC說占CPU的比,以最大話的減小heap。

附注SUN的官方說明: 

  1. 1. The throughput collector: this collector uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed on the command line. The tenured generation collector is the same as the serial collector.  
  2.   
  3. 2. The concurrent low pause collector: this collector is used if the -Xincgc™ or -XX:+UseConcMarkSweepGC is passed on the command line. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is used with the concurrent collector. The concurrent low pause collector is used if the option -XX:+UseConcMarkSweepGC is passed on the command line.  
  4.   
  5. 3. The incremental (sometimes called train) low pause collector: this collector is used only if -XX:+UseTrainGC is passed on the command line. This collector has not changed since the J2SE Platform version 1.4.2 and is currently not under active development. It will not be supported in future releases. Please see the 1.4.2 GC Tuning Document for information on this collector.  

  1. 1. The throughput collector: this collector uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed on the command line. The tenured generation collector is the same as the serial collector.  
  2.   
  3. 2. The concurrent low pause collector: this collector is used if the -Xincgc™ or -XX:+UseConcMarkSweepGC is passed on the command line. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is used with the concurrent collector. The concurrent low pause collector is used if the option -XX:+UseConcMarkSweepGC is passed on the command line.  
  4.   
  5. 3. The incremental (sometimes called train) low pause collector: this collector is used only if -XX:+UseTrainGC is passed on the command line. This collector has not changed since the J2SE Platform version 1.4.2 and is currently not under active development. It will not be supported in future releases. Please see the 1.4.2 GC Tuning Document for information on this collector.  
1. The throughput collector: this collector uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed on the command line. The tenured generation collector is the same as the serial collector.

2. The concurrent low pause collector: this collector is used if the -Xincgc™ or -XX:+UseConcMarkSweepGC is passed on the command line. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is used with the concurrent collector. The concurrent low pause collector is used if the option -XX:+UseConcMarkSweepGC is passed on the command line.

3. The incremental (sometimes called train) low pause collector: this collector is used only if -XX:+UseTrainGC is passed on the command line. This collector has not changed since the J2SE Platform version 1.4.2 and is currently not under active development. It will not be supported in future releases. Please see the 1.4.2 GC Tuning Document for information on this collector.


CMS GC Incremental mode


       當要使用 concurrent low pause collector時。在java的opt里加上 -XX:+UseConcMarkSweepGC。concurrent low pause collector另一種為CPU少的機器准備的模式。叫Incremental mode。

這樣的模式使用一個CPU來在程序執行的過程中GC,僅僅用非常少的時間暫停程序,檢查對象存活。

       在Incremental mode里,每一個收集過程中,會暫停兩次,第二次略長。第一次用來,簡單從root查詢存活對象。第二次用來,詳細檢查存活對象。

整個步驟例如以下:

  1. * stop all application threads; do the initial mark; resume all application threads(第一次暫停,初始話標記)  
  2. do the concurrent mark (uses one procesor for the concurrent work)(執行是標記)  
  3. do the concurrent pre-clean (uses one processor for the concurrent work)(准備清理)  
  4. * stop all application threads; do the remark; resume all application threads(第二次暫停。標記,檢查)  
  5. do the concurrent sweep (uses one processor for the concurrent work)(執行過程中清理)  
  6. do the concurrent reset (uses one processor for the concurrent work)(復原)  

  1. * stop all application threads; do the initial mark; resume all application threads(第一次暫停。初始話標記)  
  2. do the concurrent mark (uses one procesor for the concurrent work)(執行是標記)  
  3. do the concurrent pre-clean (uses one processor for the concurrent work)(准備清理)  
  4. * stop all application threads; do the remark; resume all application threads(第二次暫停。標記。檢查)  
  5. do the concurrent sweep (uses one processor for the concurrent work)(執行過程中清理)  
  6. do the concurrent reset (uses one processor for the concurrent work)(復原)  
* stop all application threads; do the initial mark; resume all application threads(第一次暫停,初始話標記)
* do the concurrent mark (uses one procesor for the concurrent work)(執行是標記)
* do the concurrent pre-clean (uses one processor for the concurrent work)(准備清理)
* stop all application threads; do the remark; resume all application threads(第二次暫停,標記,檢查)
* do the concurrent sweep (uses one processor for the concurrent work)(執行過程中清理)
* do the concurrent reset (uses one processor for the concurrent work)(復原)


       當要使用Incremental mode時。須要使用以下幾個變量:

  1. -XX:+CMSIncrementalMode default: disabled 啟動i-CMS模式(must with -XX:+UseConcMarkSweepGC)  
  2. -XX:+CMSIncrementalPacing default: disabled 提供自己主動校正功能  
  3. -XX:CMSIncrementalDutyCycle=<N> default50 啟動CMS的上線  
  4. -XX:CMSIncrementalDutyCycleMin=<N> default10 啟動CMS的下線  
  5. -XX:CMSIncrementalSafetyFactor=<N> default10 用來計算循環次數  
  6. -XX:CMSIncrementalOffset=<N> default0 最小循環次數(This is the percentage (0-100) by which the incremental mode duty cycle is shifted to the right within the period between minor collections.)  
  7. -XX:CMSExpAvgFactor=<N> default25 提供一個指導收集數  

  1. -XX:+CMSIncrementalMode default: disabled 啟動i-CMS模式(must with -XX:+UseConcMarkSweepGC)  
  2. -XX:+CMSIncrementalPacing default: disabled 提供自己主動校正功能  
  3. -XX:CMSIncrementalDutyCycle=<N> default50 啟動CMS的上線  
  4. -XX:CMSIncrementalDutyCycleMin=<N> default10 啟動CMS的下線  
  5. -XX:CMSIncrementalSafetyFactor=<N> default10 用來計算循環次數  
  6. -XX:CMSIncrementalOffset=<N> default0 最小循環次數(This is the percentage (0-100) by which the incremental mode duty cycle is shifted to the right within the period between minor collections.)  
  7. -XX:CMSExpAvgFactor=<N> default25 提供一個指導收集數  
-XX:+CMSIncrementalMode default: disabled 啟動i-CMS模式(must with -XX:+UseConcMarkSweepGC)
-XX:+CMSIncrementalPacing default: disabled 提供自己主動校正功能
-XX:CMSIncrementalDutyCycle=<N> default: 50 啟動CMS的上線
-XX:CMSIncrementalDutyCycleMin=<N> default: 10 啟動CMS的下線
-XX:CMSIncrementalSafetyFactor=<N> default: 10 用來計算循環次數
-XX:CMSIncrementalOffset=<N> default: 0 最小循環次數(This is the percentage (0-100) by which the incremental mode duty cycle is shifted to the right within the period between minor collections.)
-XX:CMSExpAvgFactor=<N> default: 25 提供一個指導收集數



     SUN推薦的使用參數是:
  1. -XX:+UseConcMarkSweepGC \  
  2. -XX:+CMSIncrementalMode \  
  3. -XX:+CMSIncrementalPacing \  
  4. -XX:CMSIncrementalDutyCycleMin=0 \  
  5. -XX:CMSIncrementalDutyCycle=10 \  
  6. -XX:+PrintGC Details \  
  7. -XX:+PrintGCTimeStamps \  
  8. -XX:-TraceClassUnloading  

  1. -XX:+UseConcMarkSweepGC \  
  2. -XX:+CMSIncrementalMode \  
  3. -XX:+CMSIncrementalPacing \  
  4. -XX:CMSIncrementalDutyCycleMin=0 \  
  5. -XX:CMSIncrementalDutyCycle=10 \  
  6. -XX:+PrintGC Details \  
  7. -XX:+PrintGCTimeStamps \  
  8. -XX:-TraceClassUnloading  
-XX:+UseConcMarkSweepGC \
-XX:+CMSIncrementalMode \
-XX:+CMSIncrementalPacing \
-XX:CMSIncrementalDutyCycleMin=0 \
-XX:CMSIncrementalDutyCycle=10 \
-XX:+PrintGC Details \
-XX:+PrintGCTimeStamps \
-XX:-TraceClassUnloading


注:假設使用throughput collector和concurrent low pause collector,這兩種垃圾收集器,須要適當的挺高內存大小。以為多線程做准備。

3.3、怎樣選擇collector


  • app執行在單處理器機器上且沒有pause time的要求,讓vm選擇UseSerialGC.
  • 重點考慮peak application performance(高性能),沒有pause time太嚴格要求。讓vm選擇或者UseParallelGC+UseParallelOldGC(optionally).
  • 重點考慮response time,pause time要小UseConcMarkSweepGC.

Garbage Collctor – Future

  1. Garbage First(G1)  
  2. jdk1.6 update 14 or jdk7  
  3. few flags need to set  
  4. -XX:MaxGCPauseMillis=100  
  5. -XX:GCPauseIntervalMillis=6000  

  1. Garbage First(G1)  
  2. jdk1.6 update 14 or jdk7  
  3. few flags need to set  
  4. -XX:MaxGCPauseMillis=100  
  5. -XX:GCPauseIntervalMillis=6000  
Garbage First(G1)
jdk1.6 update 14 or jdk7
few flags need to set
-XX:MaxGCPauseMillis=100
-XX:GCPauseIntervalMillis=6000


     還沒嘗試過使用…

Summary


     
     
    
   
  
  
          
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3. public class SummaryCase {  
  4.     public static void main(String[] args) throws InterruptedException {  
  5.         List<Object> caches = new ArrayList<Object>();  
  6.         for (int i = 0; i < 7; i++) {  
  7.             caches.add(new byte[1024 * 1024 * 3]);  
  8.             Thread.sleep(1000);  
  9.         }  
  10.         caches.clear();  
  11.         for (int i = 0; i < 2; i++) {  
  12.             caches.add(new byte[1024 * 1024 * 3]);  
  13.             Thread.sleep(1000);  
  14.         }  
  15.     }  
  16. }  
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3. public class SummaryCase {  
  4.     public static void main(String[] args) throws InterruptedException {  
  5.         List<Object> caches = new ArrayList<Object>();  
  6.         for (int i = 0; i < 7; i++) {  
  7.             caches.add(new byte[1024 * 1024 * 3]);  
  8.             Thread.sleep(1000);  
  9.         }  
  10.         caches.clear();  
  11.         for (int i = 0; i < 2; i++) {  
  12.             caches.add(new byte[1024 * 1024 * 3]);  
  13.             Thread.sleep(1000);  
  14.         }  
  15.     }  
  16. }  
import java.util.ArrayList;
import java.util.List;
public class SummaryCase {
    public static void main(String[] args) throws InterruptedException {
        List<Object> caches = new ArrayList<Object>();
        for (int i = 0; i < 7; i++) {
            caches.add(new byte[1024 * 1024 * 3]);
            Thread.sleep(1000);
        }
        caches.clear();
        for (int i = 0; i < 2; i++) {
            caches.add(new byte[1024 * 1024 * 3]);
            Thread.sleep(1000);
        }
    }
}


}


用以下兩種參數執行,會執行幾次YGC幾次FGC?

-Xms30M -Xmx30M -Xmn10M  -Xloggc:gc.log -XX:+PrintTenuringDistribution -XX:+UseParallelGC

  1. 2.062: [GC  
  2. Desired survivor size 1310720 bytes, new threshold 7 (max 15)  
  3.  6467K->6312K(29440K), 0.0038214 secs]  
  4. 4.066: [GC  
  5. Desired survivor size 1310720 bytes, new threshold 7 (max 15)  
  6.  12536K->12440K(29440K), 0.0036804 secs]  
  7. 6.070: [GC  
  8. Desired survivor size 1310720 bytes, new threshold 7 (max 15)  
  9.  18637K->18584K(29440K), 0.0040175 secs]  
  10. 6.074: [Full GC 18584K->18570K(29440K), 0.0031329 secs]  
  11. 8.078: [Full GC 24749K->3210K(29440K), 0.0045590 secs]  

  1. 2.062: [GC  
  2. Desired survivor size 1310720 bytes, new threshold 7 (max 15)  
  3.  6467K->6312K(29440K), 0.0038214 secs]  
  4. 4.066: [GC  
  5. Desired survivor size 1310720 bytes, new threshold 7 (max 15)  
  6.  12536K->12440K(29440K), 0.0036804 secs]  
  7. 6.070: [GC  
  8. Desired survivor size 1310720 bytes, new threshold 7 (max 15)  
  9.  18637K->18584K(29440K), 0.0040175 secs]  
  10. 6.074: [Full GC 18584K->18570K(29440K), 0.0031329 secs]  
  11. 8.078: [Full GC 24749K->3210K(29440K), 0.0045590 secs]  
2.062: [GC
Desired survivor size 1310720 bytes, new threshold 7 (max 15)
 6467K->6312K(29440K), 0.0038214 secs]
4.066: [GC
Desired survivor size 1310720 bytes, new threshold 7 (max 15)
 12536K->12440K(29440K), 0.0036804 secs]
6.070: [GC
Desired survivor size 1310720 bytes, new threshold 7 (max 15)
 18637K->18584K(29440K), 0.0040175 secs]
6.074: [Full GC 18584K->18570K(29440K), 0.0031329 secs]
8.078: [Full GC 24749K->3210K(29440K), 0.0045590 secs]

(詳細分析見 http://rdc.taobao.com/team/jm/archives/440 )

-Xms30M -Xmx30M -Xmn10M  -Xloggc:gc.log -XX:+PrintTenuringDistribution -XX:+UseSerialGC
  1. 2.047: [GC  
  2. Desired survivor size 524288 bytes, new threshold 15 (max 15)  
  3. - age   1:     142024 bytes,     142024 total  
  4.  6472K->6282K(29696K), 0.0048686 secs]  
  5. 4.053: [GC  
  6. Desired survivor size 524288 bytes, new threshold 15 (max 15)  
  7. - age   2:     141880 bytes,     141880 total  
  8.  12512K->12426K(29696K), 0.0047334 secs]  
  9. 6.058: [GC  
  10. Desired survivor size 524288 bytes, new threshold 15 (max 15)  
  11. - age   3:     141880 bytes,     141880 total  
  12.  18627K->18570K(29696K), 0.0049135 secs]  
  13. 8.063: [Full GC 24752K->3210K(29696K), 0.0077895 secs]  

  1. 2.047: [GC  
  2. Desired survivor size 524288 bytes, new threshold 15 (max 15)  
  3. - age   1:     142024 bytes,     142024 total  
  4.  6472K->6282K(29696K), 0.0048686 secs]  
  5. 4.053: [GC  
  6. Desired survivor size 524288 bytes, new threshold 15 (max 15)  
  7. - age   2:     141880 bytes,     141880 total  
  8.  12512K->12426K(29696K), 0.0047334 secs]  
  9. 6.058: [GC  
  10. Desired survivor size 524288 bytes, new threshold 15 (max 15)  
  11. - age   3:     141880 bytes,     141880 total  
  12.  18627K->18570K(29696K), 0.0049135 secs]  
  13. 8.063: [Full GC 24752K->3210K(29696K), 0.0077895 secs]  
2.047: [GC
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age   1:     142024 bytes,     142024 total
 6472K->6282K(29696K), 0.0048686 secs]
4.053: [GC
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age   2:     141880 bytes,     141880 total
 12512K->12426K(29696K), 0.0047334 secs]
6.058: [GC
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age   3:     141880 bytes,     141880 total
 18627K->18570K(29696K), 0.0049135 secs]
8.063: [Full GC 24752K->3210K(29696K), 0.0077895 secs]

(詳細分析見 http://rdc.taobao.com/team/jm/archives/458 )


四、GC調優的小樣例


例1:Heap size 設置 


JVM 堆的設置是指java程序執行過程中JVM能夠調配使用的內存空間的設置.JVM在啟動的時候會自己主動設置Heap size的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。能夠利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。


Heap size 的大小是Young Generation 和Tenured Generaion 之和。
當在JAVA_HOME下demo/jfc/SwingSet2/文件夾下執行以下的命令。


  1. java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar  

  1. java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar  
java -jar -Xmn4m -Xms16m -Xmx16m SwingSet2.jar


系統輸出為:
  1. Exception in thread ”Image Fetcher 0” java.lang.OutOfMemoryError: Java heap space  
  2. Exception in thread ”Image Fetcher 3” java.lang.OutOfMemoryError: Java heap space  
  3. Exception in thread ”Image Fetcher 1” java.lang.OutOfMemoryError: Java heap space  
  4. Exception in thread ”Image Fetcher 2” java.lang.OutOfMemoryError: Java heap space  

  1. Exception in thread “Image Fetcher 0” java.lang.OutOfMemoryError: Java heap space  
  2. Exception in thread ”Image Fetcher 3” java.lang.OutOfMemoryError: Java heap space  
  3. Exception in thread ”Image Fetcher 1” java.lang.OutOfMemoryError: Java heap space  
  4. Exception in thread ”Image Fetcher 2” java.lang.OutOfMemoryError: Java heap space  
Exception in thread "Image Fetcher 0" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 3" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 1" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Image Fetcher 2" java.lang.OutOfMemoryError: Java heap space



除了這些異常信息外。還會發現程序的響應速度變慢了。

這說明Heap size 設置偏小,GC占用了很多其它的時間。而應用分配到的執行時間較少。


提示:在JVM中假設98%的時間是用於GC且可用的Heap size 不足2%的時候將拋出此異常信息。

 


將上面的命令換成以下命令執行則應用能夠正常使用,且未拋出不論什么異常。


java -jar -Xmn4m -Xms16m -Xmx32m SwingSet2.jar


提示:Heap Size 最大不要超過可用物理內存的80%,一般的要將-Xms和-Xmx選項設置為同樣,而-Xmn為1/4的-Xmx值。


例2:Young Generation(-Xmn)的設置 


在本例中看一下Young Generation的設置不同將有什么現象發生。
假設將Young generation 的大小設置為4M ,即執行java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails
 SwingSet2.jar,


屏幕輸出例如以下(節選)

  1. [GC [DefNew: 3968K->64K(4032K), 0.0923407 secs] 3968K->2025K(32704K), 0.0931870 secs]  
  2. [GC [DefNew: 4021K->64K(4032K), 0.0356847 secs] 5983K->2347K(32704K), 0.0365441 secs]  
  3. [GC [DefNew: 3995K->39K(4032K), 0.0090603 secs] 6279K->2372K(32704K), 0.0093377 secs]  

  1. [GC [DefNew: 3968K->64K(4032K), 0.0923407 secs] 3968K->2025K(32704K), 0.0931870 secs]  
  2. [GC [DefNew: 4021K->64K(4032K), 0.0356847 secs] 5983K->2347K(32704K), 0.0365441 secs]  
  3. [GC [DefNew: 3995K->39K(4032K), 0.0090603 secs] 6279K->2372K(32704K), 0.0093377 secs]  
[GC [DefNew: 3968K->64K(4032K), 0.0923407 secs] 3968K->2025K(32704K), 0.0931870 secs]
[GC [DefNew: 4021K->64K(4032K), 0.0356847 secs] 5983K->2347K(32704K), 0.0365441 secs]
[GC [DefNew: 3995K->39K(4032K), 0.0090603 secs] 6279K->2372K(32704K), 0.0093377 secs]


將程序體制並將Young Generation的大小設置為8M,即執行

  1. java -jar -verbose:gc -Xmn8m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jar  

  1. java -jar -verbose:gc -Xmn8m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jar  
java -jar -verbose:gc -Xmn8m -Xms32m -Xmx32m -XX:+PrintGCDetails SwingSet2.jar


屏幕輸出例如以下(節選)

  1. [GC [DefNew: 7808K->192K(8000K), 0.1016784 secs] 7808K->2357K(32576K), 0.1022834 secs]  
  2. [GC [DefNew: 8000K->70K(8000K), 0.0149659 secs] 10165K->2413K(32576K), 0.0152557 secs]  
  3. [GC [DefNew: 7853K->59K(8000K), 0.0069122 secs] 10196K->2403K(32576K), 0.0071843 secs]  
  4. [GC [DefNew: 7867K->171K(8000K), 0.0075745 secs] 10211K->2681K(32576K), 0.0078376 secs]  
  5. [GC [DefNew: 7970K->192K(8000K), 0.0201353 secs] 10480K->2923K(32576K), 0.0206867 secs]  
  6. [GC [DefNew: 7979K->30K(8000K), 0.1787079 secs] 10735K->4824K(32576K), 0.1790065 secs]  

  1. [GC [DefNew: 7808K->192K(8000K), 0.1016784 secs] 7808K->2357K(32576K), 0.1022834 secs]  
  2. [GC [DefNew: 8000K->70K(8000K), 0.0149659 secs] 10165K->2413K(32576K), 0.0152557 secs]  
  3. [GC [DefNew: 7853K->59K(8000K), 0.0069122 secs] 10196K->2403K(32576K), 0.0071843 secs]  
  4. [GC [DefNew: 7867K->171K(8000K), 0.0075745 secs] 10211K->2681K(32576K), 0.0078376 secs]  
  5. [GC [DefNew: 7970K->192K(8000K), 0.0201353 secs] 10480K->2923K(32576K), 0.0206867 secs]  
  6. [GC [DefNew: 7979K->30K(8000K), 0.1787079 secs] 10735K->4824K(32576K), 0.1790065 secs]  
[GC [DefNew: 7808K->192K(8000K), 0.1016784 secs] 7808K->2357K(32576K), 0.1022834 secs]
[GC [DefNew: 8000K->70K(8000K), 0.0149659 secs] 10165K->2413K(32576K), 0.0152557 secs]
[GC [DefNew: 7853K->59K(8000K), 0.0069122 secs] 10196K->2403K(32576K), 0.0071843 secs]
[GC [DefNew: 7867K->171K(8000K), 0.0075745 secs] 10211K->2681K(32576K), 0.0078376 secs]
[GC [DefNew: 7970K->192K(8000K), 0.0201353 secs] 10480K->2923K(32576K), 0.0206867 secs]
[GC [DefNew: 7979K->30K(8000K), 0.1787079 secs] 10735K->4824K(32576K), 0.1790065 secs]


那么依據GC輸出的信息(這里取第一行)做一下Minor收集的比較。能夠看出兩次的Minor收集分別在Young generation中找回3904K(3968K->64K)和7616K(7808K->192K)而對於整個jvm則找回 1943K(3968K->2025)和5451K(7808K->2357K)。第一種情況下Minor收集了大約50%(1943/3904)的對象,而另外的50%的對象則被移到了tenured generation。在第二中情況下Minor收集了大約72%的對象,僅僅有不到30%的對象被移到了Tenured Generation.這個樣例說明此應用在的Young generation 設置為4m時顯的偏小。
提示:一般的Young Generation的大小是整個Heap size的1/4。Young generation的minor收集率應一般在70%以上。當然在實際的應用中須要依據詳細情況進行調整。


例3:Young Generation相應用響應的影響 


還是使用-Xmn4m 和-Xmn8m進行比較。先執行以下的命令

  1. java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime SwingSet2.jar  

  1. java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime SwingSet2.jar  
java -jar -verbose:gc -Xmn4m -Xms32m -Xmx32m -XX:+PrintGCDetails -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime SwingSet2.jar


屏幕輸出例如以下(節選)
  1. Application time: 0.5114944 seconds  
  2. [GC [DefNew: 3968K->64K(4032K), 0.0823952 secs] 3968K->2023K(32704K), 0.0827626 secs]  
  3. Total time for which application threads were stopped: 0.0839428 seconds  
  4. Application time: 0.9871271 seconds  
  5. [GC [DefNew: 4020K->64K(4032K), 0.0412448 secs] 5979K->2374K(32704K), 0.0415248 secs]  
  6. Total time for which application threads were stopped: 0.0464380 seconds  

  1. Application time: 0.5114944 seconds  
  2. [GC [DefNew: 3968K->64K(4032K), 0.0823952 secs] 3968K->2023K(32704K), 0.0827626 secs]  
  3. Total time for which application threads were stopped: 0.0839428 seconds  
  4. Application time: 0.9871271 seconds  
  5. [GC [DefNew: 4020K->64K(4032K), 0.0412448 secs] 5979K->2374K(32704K), 0.0415248 secs]  
  6. Total time for which application threads were stopped: 0.0464380 seconds  
Application time: 0.5114944 seconds
[GC [DefNew: 3968K->64K(4032K), 0.0823952 secs] 3968K->2023K(32704K), 0.0827626 secs]
Total time for which application threads were stopped: 0.0839428 seconds
Application time: 0.9871271 seconds
[GC [DefNew: 4020K->64K(4032K), 0.0412448 secs] 5979K->2374K(32704K), 0.0415248 secs]
Total time for which application threads were stopped: 0.0464380 seconds


Young Generation 的Minor收集占用的時間能夠計算例如以下

應用線程被中斷的總時常/(應用執行總時?L+應用線程被中斷的總時常),那么在本例中垃圾收集占用的時?L約為系統的5%~14%。

那么當垃圾收集占用的時間的比例越大的時候。系統的響應將越慢。


提示:對於互聯網應用系統的響應略微慢一些。用戶是能夠接受的,可是對於GUI類型的應用響應速度慢將會給用戶帶來非常不好的體驗。


例4:怎樣決定Tenured Generation 的大小 


分別以-Xmn8m -Xmx32m和-Xmn8m -Xmx64m進行對照,先執行

  1. java -verbose:gc -Xmn8m -Xmx32m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類  

  1. java -verbose:gc -Xmn8m -Xmx32m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類  
java -verbose:gc -Xmn8m -Xmx32m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類


命令行將提示(僅僅提取了Major收集)

  1. 111.042: [GC 111.042: [DefNew: 8128K->8128K(8128K), 0.0000505 secs]111.042: [Tenured: 18154K->2311K(24576K), 0.1290354 secs] 26282K->2311K(32704K), 0.1293306 secs]  
  2. 122.463: [GC 122.463: [DefNew: 8128K->8128K(8128K), 0.0000560 secs]122.463: [Tenured: 18630K->2366K(24576K), 0.1322560 secs] 26758K->2366K(32704K), 0.1325284 secs]  
  3. 133.896: [GC 133.897: [DefNew: 8128K->8128K(8128K), 0.0000443 secs]133.897: [Tenured: 18240K->2573K(24576K), 0.1340199 secs] 26368K->2573K(32704K), 0.1343218 secs]  
  4. 144.112: [GC 144.112: [DefNew: 8128K->8128K(8128K), 0.0000544 secs]144.112: [Tenured: 16564K->2304K(24576K), 0.1246831 secs] 24692K->2304K(32704K), 0.1249602 secs]  

  1. 111.042: [GC 111.042: [DefNew: 8128K->8128K(8128K), 0.0000505 secs]111.042: [Tenured: 18154K->2311K(24576K), 0.1290354 secs] 26282K->2311K(32704K), 0.1293306 secs]  
  2. 122.463: [GC 122.463: [DefNew: 8128K->8128K(8128K), 0.0000560 secs]122.463: [Tenured: 18630K->2366K(24576K), 0.1322560 secs] 26758K->2366K(32704K), 0.1325284 secs]  
  3. 133.896: [GC 133.897: [DefNew: 8128K->8128K(8128K), 0.0000443 secs]133.897: [Tenured: 18240K->2573K(24576K), 0.1340199 secs] 26368K->2573K(32704K), 0.1343218 secs]  
  4. 144.112: [GC 144.112: [DefNew: 8128K->8128K(8128K), 0.0000544 secs]144.112: [Tenured: 16564K->2304K(24576K), 0.1246831 secs] 24692K->2304K(32704K), 0.1249602 secs]  
111.042: [GC 111.042: [DefNew: 8128K->8128K(8128K), 0.0000505 secs]111.042: [Tenured: 18154K->2311K(24576K), 0.1290354 secs] 26282K->2311K(32704K), 0.1293306 secs]
122.463: [GC 122.463: [DefNew: 8128K->8128K(8128K), 0.0000560 secs]122.463: [Tenured: 18630K->2366K(24576K), 0.1322560 secs] 26758K->2366K(32704K), 0.1325284 secs]
133.896: [GC 133.897: [DefNew: 8128K->8128K(8128K), 0.0000443 secs]133.897: [Tenured: 18240K->2573K(24576K), 0.1340199 secs] 26368K->2573K(32704K), 0.1343218 secs]
144.112: [GC 144.112: [DefNew: 8128K->8128K(8128K), 0.0000544 secs]144.112: [Tenured: 16564K->2304K(24576K), 0.1246831 secs] 24692K->2304K(32704K), 0.1249602 secs]


再執行

  1. java -verbose:gc -Xmn8m -Xmx64m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類  

  1. java -verbose:gc -Xmn8m -Xmx64m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類  
java -verbose:gc -Xmn8m -Xmx64m-XX:+PririntGCDetails -XX:+PrintGCTimeStamps java類


命令行將提示(僅僅提取了Major收集)

  1. 90.597: [GC 90.597: [DefNew: 8128K->8128K(8128K), 0.0000542 secs]90.597: [Tenured: 49841K->5141K(57344K), 0.2129882 secs] 57969K->5141K(65472K), 0.2133274 secs]  
  2. 120.899: [GC 120.899: [DefNew: 8128K->8128K(8128K), 0.0000550 secs]120.899: [Tenured: 50384K->2430K(57344K), 0.2216590 secs] 58512K->2430K(65472K), 0.2219384 secs]  
  3. 153.968: [GC 153.968: [DefNew: 8128K->8128K(8128K), 0.0000511 secs]153.968: [Tenured: 51164K->2309K(57344K), 0.2193906 secs] 59292K->2309K(65472K), 0.2196372 secs]  

  1. 90.597: [GC 90.597: [DefNew: 8128K->8128K(8128K), 0.0000542 secs]90.597: [Tenured: 49841K->5141K(57344K), 0.2129882 secs] 57969K->5141K(65472K), 0.2133274 secs]  
  2. 120.899: [GC 120.899: [DefNew: 8128K->8128K(8128K), 0.0000550 secs]120.899: [Tenured: 50384K->2430K(57344K), 0.2216590 secs] 58512K->2430K(65472K), 0.2219384 secs]  
  3. 153.968: [GC 153.968: [DefNew: 8128K->8128K(8128K), 0.0000511 secs]153.968: [Tenured: 51164K->2309K(57344K), 0.2193906 secs] 59292K->2309K(65472K), 0.2196372 secs]  
90.597: [GC 90.597: [DefNew: 8128K->8128K(8128K), 0.0000542 secs]90.597: [Tenured: 49841K->5141K(57344K), 0.2129882 secs] 57969K->5141K(65472K), 0.2133274 secs]
120.899: [GC 120.899: [DefNew: 8128K->8128K(8128K), 0.0000550 secs]120.899: [Tenured: 50384K->2430K(57344K), 0.2216590 secs] 58512K->2430K(65472K), 0.2219384 secs]
153.968: [GC 153.968: [DefNew: 8128K->8128K(8128K), 0.0000511 secs]153.968: [Tenured: 51164K->2309K(57344K), 0.2193906 secs] 59292K->2309K(65472K), 0.2196372 secs]


能夠看出在Heap size 為32m的時候系統等候時間約為0.13秒左右,而設置為64m的時候等候時間則增大到0.22秒左右了。可是在32m的時候系統的Major收集間隔為 10秒左右,而Heap size 添加到64m的時候為30秒。那么應用在執行的時候是選擇32m還是64m呢? 假設應用是web類型(即要求有大的吞吐量)的應用則使用64m(即 heapsize大一些)的比較好。對於要求實時響應要求較高的場合(比如GUI型的應用)則使用32m比較好一些。 
注意:
1。由於在JVM5執行時已經對Heap-size進行了優化,所以在能確定java應用執行時不會超過默認的Heap size的情況下建議不要對這些值進行改動。
2。

Heap size的 -Xms -Xmn 設置不要超出物理內存的大小。

否則會提示“Error occurred during initialization of VM Could not reserve enough space for object heap”。


例5:怎樣縮短minor收集的時間 


以下比較一下採用-XX:+UseParNewGC選項和不採用它的時候的minor收集將有什么不同。

先執行

  1. java -jar -server -verbose:gc -Xmn8m -Xms32m -Xmx32m SwingSet2.jar   

  1. java -jar -server -verbose:gc -Xmn8m -Xms32m -Xmx32m SwingSet2.jar   
java -jar -server -verbose:gc -Xmn8m -Xms32m -Xmx32m SwingSet2.jar 


系統將輸出例如以下信息(片段〕
  1. [GC 7807K->2641K(32576K), 0.0676654 secs]  
  2. [GC 10436K->3108K(32576K), 0.0245328 secs]  
  3. [GC 10913K->3176K(32576K), 0.0072865 secs]  
  4. [GC 10905K->4097K(32576K), 0.0223928 secs]  

  1. [GC 7807K->2641K(32576K), 0.0676654 secs]  
  2. [GC 10436K->3108K(32576K), 0.0245328 secs]  
  3. [GC 10913K->3176K(32576K), 0.0072865 secs]  
  4. [GC 10905K->4097K(32576K), 0.0223928 secs]  
[GC 7807K->2641K(32576K), 0.0676654 secs]
[GC 10436K->3108K(32576K), 0.0245328 secs]
[GC 10913K->3176K(32576K), 0.0072865 secs]
[GC 10905K->4097K(32576K), 0.0223928 secs]


之后再執行 

  1. java -jar -server -verbose:gc -XX:+UseParNewGC -Xmn8m -Xms32m -Xmx32m SwingSet2.jar  

  1. java -jar -server -verbose:gc -XX:+UseParNewGC -Xmn8m -Xms32m -Xmx32m SwingSet2.jar  
java -jar -server -verbose:gc -XX:+UseParNewGC -Xmn8m -Xms32m -Xmx32m SwingSet2.jar


系統將輸出例如以下信息(片段〕
  1. [ParNew 7808K->2656K(32576K), 0.0447687 secs]  
  2. [ParNew 10441K->3143K(32576K), 0.0179422 secs]  
  3. [ParNew 10951K->3177K(32576K), 0.0031914 secs]  
  4. [ParNew 10985K->3867K(32576K), 0.0154991 secs]  

  1. [ParNew 7808K->2656K(32576K), 0.0447687 secs]  
  2. [ParNew 10441K->3143K(32576K), 0.0179422 secs]  
  3. [ParNew 10951K->3177K(32576K), 0.0031914 secs]  
  4. [ParNew 10985K->3867K(32576K), 0.0154991 secs]  
[ParNew 7808K->2656K(32576K), 0.0447687 secs]
[ParNew 10441K->3143K(32576K), 0.0179422 secs]
[ParNew 10951K->3177K(32576K), 0.0031914 secs]
[ParNew 10985K->3867K(32576K), 0.0154991 secs]


非常顯然使用了-XX:+UseParNewGC選項的minor收集的時間要比不使用的時候優。


例6:怎樣縮短major收集的時間 


以下比較一下採用-XX:+UseConcMarkSweepGC選項和不採用它的時候的major收集將有什么不同。

先執行

  1. java -jar -verbose:gc -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar  

  1. java -jar -verbose:gc -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar  
java -jar -verbose:gc -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar


系統將輸出例如以下信息(片段〕
  1. [Full GC 22972K->18690K(262080K), 0.2326676 secs]  
  2. [Full GC 18690K->18690K(262080K), 0.1701866 secs  

  1. [Full GC 22972K->18690K(262080K), 0.2326676 secs]  
  2. [Full GC 18690K->18690K(262080K), 0.1701866 secs  
[Full GC 22972K->18690K(262080K), 0.2326676 secs]
[Full GC 18690K->18690K(262080K), 0.1701866 secs


之后再執行 

  1. java -jar -verbose:gc -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar  

  1. java -jar -verbose:gc -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar  
java -jar -verbose:gc -XX:+UseParNewGC -Xmn64m -Xms256m -Xmx256m SwingSet2.jar


系統將輸出例如以下信息(片段〕
  1. [Full GC 56048K->18869K(260224K), 0.3104852 secs]  

  1. [Full GC 56048K->18869K(260224K), 0.3104852 secs]  
[Full GC 56048K->18869K(260224K), 0.3104852 secs]


提示:此選項在Heap Size 比較大並且Major收集時間較長的情況下使用更合適。


例7:關於-server選項


 在JVM中將執行中的類認定為server-class的時候使用此選項。

SUN 的Hot Spot JVM5 假設推斷到系統的配置滿足例如以下條件則自己主動將執行的類認定為server-class,並且會自己主動設置jvm的選項(當沒有手工設置這選項的時候〕並且 HOTSPOT JVM5提供了自己主動調優的功能,他會依據JVM的執行情況進行調整。假設沒有特別的須要是不須要太多的人工干預的。SUN形象的稱這個機制為“人體工學 ”(Ergonomics〕。詳細能夠參考http://java.sun.com/docs/hotspot/gc5.0/ergo5.html
*.具有2個或很多其它個物理的處理器
*.具有2G或者很多其它的物理內存
提示:此選項要放在全部選項的前面。

比如:java -server 其它選項 java類


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM