1、指定垃圾收集器
- -XX:+UseSerialGC 指定使用串行垃圾收集器,新生代及老年代都是串行收集,在大堆或者多核cpu的環境中不大適合使用該種垃圾收集器
- -XX:+UseParallelGC,并行垃圾收集器,新生代使用并行收集,老年代使用串行收集
- -XX:+UseParallelOldGC,并行垃圾收器,新生代使用并行手機,老年代使用并行收集,在一些低版本的JVM該參數不支持或者不生效,這兩種垃圾收集適合不在乎延時需要高吞吐的環境下使用,比如說一些批處理程序,
- -XX:+UseConcMarkSweepGC,并發垃圾收集,新生代使用并行收集,老年代采用并發收集,適合低延遲應用使用該種垃圾器。使用并發垃圾收集,相當于自動添加了參數-XX:+UseParNewGC
- -XX:+UseG1GC,使用G1垃圾收集,該種垃圾收集器比較復雜,目前在此種垃圾收集的調優經驗較少,在需要大堆的應用可以考慮使用,相比并發垃圾收集器,其產生的碎片更少,且可以通過參數控制垃圾收集過程中的停頓時間。
2、調整堆大小
在描述調整堆大小參數,先用一張圖描述JVM堆的分布情況:
其中新生代由Eden和s0和s1組成,有時候s0也叫做from,s1叫做to。現代JVM都是將堆分成幾個不同的區間,劃分的方法主要是根據對象的存活時間長短將整個jvm內存分為新生代,老年代、永久代。相應的主要參數有:
- -Xms<n>[g|m|k]:調整堆的最小大小,比如:-Xms1G,表示堆最小為1G,在系統啟動階段JVM直接向系統申請1G內存,此參數相當于參數-XX:InitialHeapSize=n[g|m|k];
- -Xmx<n>[g|m|k]:調整堆的最大大小,比如:-Xms1G表示堆最大為1G,此參數相當于參數-XX:MaxHeapSize=n[g|m|k];
- -XX:MinHeapFreeRatio=n,指定堆最小空余比例,當堆中空余內存比例小于該參數指定值時,JVM將增大內存大小直到最大堆大小,默認40;
- -XX:MaxHeapFreeRatio=n,指定堆最大空余比例,當堆中空余比例大于該參數制定值,JVM將減少內存大小,直到最小堆大小,默認為70;
JVM將在發生FGC之后,根據這兩個參數調整整個對的大小,FGC一般消耗的時間較多,為了降低延遲,一般將最小堆大小和最大堆大小設置成一樣的。 - -XX:NewRatio=n,老年代與新生代內存占比,-XX:NewRatio=4表示年輕代是老年代內存的1/4,也就是說年輕代占用總堆內存的1/5;
- -XX:SurvivorRatio=n,Eden區與1個survivor區域內存占比,-XX:SurvivorRatio=8,表示EdenEden區域的內存是一個survivor區域內存的8倍,一共兩個survivor區域,因此survivor占用新生代的1/10;
- -XX:PermSize=<n>[g|m|k],-XX:MaxPermSize=<n>[g|m|k],這兩個參數用于制定永久代內存大小,這個兩個參數在jdk8中已經失效;
- -XX:MetaspaceSize=<n>[g|m|k], -XX:MaxMetaspaceSize=<n>[g|m|k],在jdk中使用這兩個參數指定元數據空間大小;
- -XX:TargetSurvivorRatio=n,設定survivor區的目標使用率,默認是50%;
- -XX:MaxDirectMemorySize=<n>[g|m|k],設置直接內存的大小,在使用一些nio框架時最好設置一下此參數,此參數如果過小也有可能導致頻繁觸發FGC;
- -Xss<n>[g|m|k],指定Java線程棧的大小,默認值受環境影響,Xss越大,進程能運行的最大線程數就少,如果設置的過小,容易導致StackOverflowError錯誤;
3、收集gc日志
- -verbose:gc,輸出gc日志信息,默認輸出到標準輸出,參數與-XX:+PrintGCDetails作用一致;
- -XX:+PrintGCDetails,打印gc日志,打印的出日志包含日志收集原因,歌區域變化情況,以及用時;
- -XX:+PrintGCDateStamps,日志中輸出時間戳;
- -XX:+PrintGCTimeStamps,日志中輸出時間戳,與PrintGCDateStamps參數不同的地方在于,此參數輸出的時間是相對與應用啟動時間的差值;
- -Xloggc:filename,把gc日志信息輸入到指定文件中,
- -XX:+PrintGCApplicationStoppedTime,打印垃圾收集期間應用被暫停的時間;
- -XX:+PrintGCApplicationConcurrentTime,垃圾收集之前打印出應用未中斷的執行時間;
- -XX:+UseGCLogFileRotation, -XX:GCLogFileSize=n,這兩個參數用于設置gc文件滾動和設置滾動日志文件的個數,為了防止單個gc日志文件太大,生產上建議加上這兩個參數;
4、CMS垃圾收集器參數
調優CMS垃圾收集器比調優吞吐量垃圾收集器復雜許多,下面列出一些用于設置CMS收集器的參數:
- -XX:CMSInitiatingOccupancyFraction=n,設置CMS垃圾收集器啟動回收老年代的時機,當老年代對象占比超過n時,就啟動一次CMS回收周期,注意:這個參數只是設定首次CMS垃圾回收;
- -XX:+UseCMSInitiatingOccupancyOnly,使用這個參數可以使CMS一直按照CMSInitiatingOccupancyFraction設定的值啟動;
- -XX:CMSInitiatingPermOccupancyFraction=n,設置永久代內存占比超過n啟動cms回收,此參數需要配合參數-XX:+CMSClassUnloadingEnabled一起使用(Java8默認開啟);
- -XX:+CMSParallelInitialEnabled, 用于開啟CMS initial-mark階段采用多線程的方式進行標記,用于提高標記速度,在Java8開始已經默認開啟;
- -XX:+CMSParallelRemarkEnabled,用戶開啟CMS remark階段采用多線程的方式進行重新標記,默認開啟;
- -XX:CMSFullGCsBeforeCompaction,我們知道cms垃圾收集器會產生內存碎片,該參數用于設置多少次CMS gc之后進行一次內存壓縮;該參數默認值為0;
- -XX:+ExplicitGCInvokesConcurrent 、-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses這兩個參數用戶指定hotspot虛擬在執行System.gc()時使用CMS周期;
- -XX:+CMSScavengeBeforeRemark,強制hotspot虛擬機在cms remark階段之前做一次minor gc,用于提高remark階段的速度;
- -XX:ConcGCThreads=n,設置并發垃圾收集的線程數,默認該值是基于ParallelGCThreads計算出來的;
- -XX:+CMSPrecleaningEnabled,指定CMS是否需要進行Pre cleaning這個階段,這個階段的主要工作是:1、在并發標記階段階段由于業務線程同步在跑,新生代中對象有可能引用到老年代的對象,產生新的引用關系,這個時候需要重新標記出老年代中被引用的對象;2、老年代中對象引用關系發生變化,這個需要把引用關系發生變化的卡表(card table)標記為dirty,提高remark標記的效率;
- -XX:CMSMaxAbortablePrecleanTime=n,設置cms abortable pre階段最長持續時間,單位為s,默認值5s。abortable prelean階段默認在Eden區大于2M啟動(通過參數:-XX:CMSScheduleRemarkEdenSizeThreshold =n設置),直到Eden區域占用率超過50%(通過參數:-XX:CMSScheduleRemarkEdenPenetration=n)時結束,同時還可以指定參數-XX:CMSMaxAbortablePrecleanLoops=n設置該階段的循環次數(默認0,表示不限制次數),為了防止abortable pre clean階段陷入無限等待,故設置一個最長的持續時間,達到最長持續時間之后,該階段終止,進入remark階段;
5、其他參數
-XX:+DisableExplicitGC,禁止hotspot執行System.gc(),默認禁用;
-XX:+ScavengeBeforeFullGC,在執行full gc之前執行一次minor gc,默認開啟;
-XX:MaxTenuringThreshold=n,設定新生代的對象在經歷多少次minor gc之后將轉移到老年代,默認是15;
-XX:+HeapDumpOnOutOfMemoryError,在hotspot發生OOM時打印出堆,默認打印到應用工作目錄,文件名稱為java_pid%p.hprof;
-XX:HeapDumpPath=xx,指定hotspot虛擬機OOM時堆轉儲文件的path;
-XX:ErrorFile=xx,設置JVM crash時生成crash文件的路徑,默認為./hs_err_pid%p.log;
-XX:+ParallelRefProcEnabled,采用多線程的方式發現需要處理的finalize方法的對象,非多線程執行對象的finalize方法;
-XX:ParallelGCThreads=n,設置并行收集的線程數,默認值采用Runtime.getRuntime().availableProcessors()來確定。不過是建立在返回值小于等于8的情況下,反之,會使用Runtime.availableProcessors()*5/8作為線程數。
-XX:+UseAdaptiveSizePolicy,開啟自適應調整JAVA內存策略,在使用吞吐量垃圾收集器時,該參數用于讓jvm自行調整Eden區和Survivor區空間的大小,新生代與老年代空間的大小;
-XX:+PrintAdaptiveSizePolicy,可以打印出survivor的一些詳細信息,關于survivor區間是否溢出,是否有對象轉移到老年代;
-XX:+PrintTenuringDistribution,顯示出survivor區間有效對象的年齡分布情況,可以通過該參數的輸出確定出survivor大小以及MaxTenuringThreshold的值;
-XX:MaxGCPauseMillis=n,設置最大gc停頓時間,這個時間不是設置的越小越好,此參數只在ps收集器上有效,不建議修改此參數的值;
-XX:GCTimeRatio,設置垃圾收集時間占總時間的比率,默認為99,也就是說垃圾收集時間占用總時間的1%,此參數只在ps收集器上有效;
-XX:+HeapDumpAfterFullGC,在執行一次FGC之后打印出Heap到文件;
-XX:+HeapDumpBeforeFullGC,在執行一次FGC之前打印出Heap到文件,這兩個參數主要用于調試;
-XX:+PrintHeapAtGC,打印gc前后堆詳細信息,不管是minor gc還是full gc都會打印;
-XX:+GCLockerInvokesConcurrent,在執行gc之前都需要先先查看 gc locker是否被java線程持有,如果存在gc locker被持有的情況則忽略此次gc,在所有java線程完全釋放gc locker之后補償一次gc。此參數指定,如果是fgc的話,則補償一次CMS back groud fgc。
-XX:ReservedCodeCacheSize=<n>[g|m|k]、-XX:InitialCodeCacheSize=<n>[g|m|k],指定代碼緩存的大小,用于保存已編譯方法生成的本地代碼,如果代碼緩存被占滿JVM會發出警告信息,并切換到interpreted-only模式,JIT編譯器被停用,字節碼將不會再編譯成機器碼。這樣的話對JVM的性能影響很大;
-XX:+UseCodeCacheFlushing,如果代碼緩存不斷增長導致代碼緩存空間不夠,使用該參數讓jvm放棄一些被編譯的代碼,避免代碼緩存被占滿時JVM切換到interpreted-only的情況;
-
-XX:+DoEscapeAnalysis,開啟逃逸分析,逃逸分析是一種分析對象范圍的技術,在一些情況一個線程分配的對象可能會被其他對象使用,這種現象叫做“逃逸”,如果一個對象沒有“逃逸”,則可以運用一些額外的優化技術,這種優化技術“逃逸分析”。通過“逃逸分析” JIT可以使用如下技術優化:
- 棧上分配
- 消滅同步
- 消滅垃圾回收讀寫障礙
- 對象爆炸
-XX:+UseBiasedLocking,開啟偏向鎖,偏向鎖是是鎖偏愛上次使用它的線程,在非競爭鎖的場景下,可以實現無鎖的開銷。
-XX:+UseLargePages,開啟使用大頁面,使用大頁面可以提高TLB(translation lookaside buffer(轉換后備緩存區))的緩存命中率;
-XX:PretenureSizeThreshold=n,指定對象占用的字節數超過n之后直接在老年代中分配,默認值0,表示最大值;
-XX:+OmitStackTraceInFastThrow,一些頻繁拋出的異常,JVM為了性能優化而拋出沒有堆棧的異常,默認開啟,
-XX:+PrintFlagsInitial、-XX:+PrintFlagsFinal,打印出設置的JVM參數和最終生效的JVM參數和他們的值,-XX:+PrintCommandLineFlags打印出被修改的JVM參數,一般在啟動應用添加此參數打印出引用啟動時添加的JVM參數,在應用運行過程中一些JVM參數可能會被修改掉(通過jinfo工具);
-XX:+PrintSafepointStatistics,打印安全點統計信息,-XX:PrintSafepointStatisticsCount=n設置打印安全點統計信息的次數;
-XX:+PrintReferenceGC,打印gc時處理的reference情況;
-XX:+UseCompressedOops,開啟壓縮指針,壓縮指針主要是為了解決32位操作系統內存尋址范圍只有4G的限制,開啟壓縮指針最大尋址范圍增加到32G;如果內存超過32G(Xmx>32G),開啟該參數無效;
-XX:+ParallelRefProcEnabled,使用此參數激活多線程方式的引用處理,截止到目前的jdk8該參數默認關閉,如果在gc中發現處理ref處理的時間過長,可以通過參數-XX:+PrintReferenceGC打印出每次垃圾收集中記錄每個引用對象類型的統計數據,另外如果發現有大量軟引用正在被處理,可以使用參數-XX:SoftRefLRUPolicyPerMB調整軟件用的處理策略,該參數的默認值為1000(ms),該參數的含義是,使用該參數設置的值乘以java堆可用空間(以兆為單位)的出來的值,若軟引用在這段時間內沒有被訪問,那么這些軟引用將會被回收,調優引用處理的目標主要有兩點:第一是降低引用在gc過程中處理時間,第二是降低heap的占用空間,減少垃圾收集頻率和最終需要復制的時間;
總結
本文列舉了一些常用的JVM參數,至于如何調整各參數已達到JVM的最佳性能要以場景而定,
鏈接:http://www.lxweimin.com/p/12eda04e6f87
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。