日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM基础(6)-常用参数总结

發布時間:2024/4/14 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM基础(6)-常用参数总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考文章:

并發編程網:http://ifeve.com/useful-jvm-flags-part-4-heap-tuning/

一、參數分類

HotSpot JVM 提供了三類參數。

  • 第一類包括了標準參數。顧名思義,標準參數中包括功能和輸出的參數都是很穩定的,很可能在將來的 JVM 版本中不會改變。你可以用 java 命令(或者是用 java -help)檢索出所有標準參數。我們在第一部分中已經見到過一些標準參數,例如:-server。
  • 第二類是 X 參數,非標準化的參數在將來的版本中可能會改變。所有的這類參數都以 - X 開始,并且可以用 java -X 來檢索。注意,不能保證所有參數都可以被檢索出來,其中就沒有 - Xcomp。
  • 第三類是包含 XX 參數(到目前為止最多的),它們同樣不是標準的,甚至很長一段時間內不被列出來(最近,這種情況有改變 ,我們將在本系列的第三部分中討論它們)。然而,在實際情況中 X 參數和 XX 參數并沒有什么不同。X 參數的功能是十分穩定的,然而很多 XX 參數仍在實驗當中(主要是 JVM 的開發者用于 debugging 和調優 JVM 自身的實現)。值的一讀的介紹非標準參數的文檔?HotSpot JVM documentation,其中明確的指出 XX 參數不應該在不了解的情況下使用。這是真的,并且我認為這個建議同樣適用于 X 參數(同樣一些標準參數也是)。不管類別是什么,在使用參數之前應該先了解它可能產生的影響。

用一句話來說明 XX 參數的語法。所有的 XX 參數都以”-XX:” 開始,但是隨后的語法不同,取決于參數的類型:

  • 對于布爾類型的參數,我們有”+” 或”-“,然后才設置 JVM 選項的實際名稱。例如,-XX:+?用于激活?選項,而 - XX:-?用于注銷選項。
  • 對于需要非布爾值的參數,如 string 或者 integer,我們先寫參數的名稱,后面加上”=”,最后賦值。例如, -XX:=?給?賦值?。?

現在讓我們來看看 JIT 編譯方面的一些 XX 參數:-XX:+PrintCompilation and -XX:+CITime

-XX:+PrintCompilation

$ java -server -XX:+PrintCompilation Benchmark1 java.lang.String::hashCode (64 bytes)2 java.lang.AbstractStringBuilder::stringSizeOfInt (21 bytes)3 java.lang.Integer::getChars (131 bytes)4 java.lang.Object::<init> (1 bytes) --- n java.lang.System::arraycopy (static)5 java.util.HashMap::indexFor (6 bytes)6 java.lang.Math::min (11 bytes)7 java.lang.String::getChars (66 bytes)8 java.lang.AbstractStringBuilder::append (60 bytes)9 java.lang.String::<init> (72 bytes)10 java.util.Arrays::copyOfRange (63 bytes)11 java.lang.StringBuilder::append (8 bytes)12 java.lang.AbstractStringBuilder::<init> (12 bytes)13 java.lang.StringBuilder::toString (17 bytes)14 java.lang.StringBuilder::<init> (18 bytes)15 java.lang.StringBuilder::append (8 bytes) [...]29 java.util.regex.Matcher::reset (83 bytes)

每當一個方法被編譯,就輸出一行 - XX:+PrintCompilation。

每行都包含順序號(唯一的編譯任務 ID)和已編譯方法的名稱和大小。因此,順序號 1,代表編譯 String 類中的 hashCode 方法到原生代碼的信息。

根據方法的類型和編譯任務打印額外的信息。例如,本地的包裝方法前方會有”n” 參數,像上面的 System::arraycopy 一樣。注意這樣的方法不會包含順序號和方法占用的大小,因為它不需要編譯為本地代碼。

同樣可以看到被重復編譯的方法,例如 StringBuilder::append 順序號為 11 和 15。輸出在順序號 29 時停止 ,這表明在這個 Java 應用運行時總共需要編譯 29 個方法。

-XX:+CITime

設置 - XX:+CITime,我們可以在 JVM 關閉時得到各種編譯的統計信息,例如:

Accumulated compiler times (for compiled methods only) ------------------------------------------------Total compilation time : 0.165 sStandard compilation : 0.165 s, Average : 0.000On stack replacement : 0.000 s, Average : -1.#IODetailed C1 TimingsSetup time: 0.000 s ( 0.0%)Build IR: 0.080 s (49.9%)Optimize: 0.008 s ( 4.8%)RCE: 0.001 s ( 0.6%)Emit LIR: 0.059 s (36.6%)LIR Gen: 0.011 s ( 6.8%)Linear Scan: 0.047 s (29.5%)LIR Schedule: 0.000 s ( 0.0%)Code Emission: 0.015 s ( 9.2%)Code Installation: 0.007 s ( 4.3%)Instruction Nodes: 60882 nodesTotal compiled methods : 667 methodsStandard compilation : 667 methodsOn stack replacement : 0 methodsTotal compiled bytecodes : 95744 bytesStandard compilation : 95744 bytesOn stack replacement : 0 bytesAverage compilation speed: 581621 bytes/snmethod code size : 474048 bytesnmethod total size : 1057916 bytes

?

二、打印所有-XX參數值

-XX:+PrintFlagsFinal and -XX:+PrintFlagsInitial

$ java -XX:+PrintFlagsFinal Benchmark [Global flags] uintx AdaptivePermSizeWeight = 20 {product} uintx AdaptiveSizeDecrementScaleFactor = 4 {product} uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product} uintx AdaptiveSizePausePolicy = 0 {product}[...] uintx YoungGenerationSizeSupplementDecay = 8 {product} uintx YoungPLABSize = 4096 {product}bool ZeroTLAB = false {product}intx hashCode = 0 {product}

表格的每一行包括五列,來表示一個 XX 參數。第一列表示參數的數據類型,第二列是名稱,第四列為值,第五列是參數的類別。第三列”=” 表示第四列是參數的默認值,而“:=” 表明了參數被用戶或者 JVM 賦值了。

我們也能指定參數 -XX:+UnlockExperimentalVMOptions 和 -XX:+UnlockDiagnosticVMOptions;來解鎖任何額外的隱藏參數,例如:

$ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark

這篇文章解釋了第5列參數:http://q-redux.blogspot.jp/2011/01/inspecting-hotspot-jvm-options.html

-XX:+PrintCommandLineFlags

這個參數讓 JVM 打印出那些已經被用戶或者 JVM 設置過的詳細的 XX 參數的名稱和值。

換句話說,它列舉出 -XX:+PrintFlagsFinal的結果中第三列有“:=”的參數。以這種方式,我們可以用 - XX:+PrintCommandLineFlags 作為快捷方式來查看修改過的參數。看下面的例子。

$ java -server -XX:+PrintCommandLineFlags Benchmark -XX:InitialHeapSize=57505088 -XX:MaxHeapSize=920081408 -XX:ParallelGCThreads=4 -XX:+PrintCommandLineFlags -XX:+UseParallelGC

現在如果我們每次啟動 java 程序的時候設置 -XX:+PrintCommandLineFlags 并且輸出到日志文件上,這樣會記錄下我們設置的 JVM 參數對應用程序性能的影響。

建議 –XX:+PrintCommandLineFlags 這個參數應該總是設置在 JVM 啟動的配置項里。因為你從不知道你什么時候會需要這些信息。

三、內存相關參數

-Xms and -Xmx (or: -XX:InitialHeapSize and -XX:MaxHeapSize)

?堆大小設置,建議相同以獲取穩定的堆環境

java -Xms2g -Xmx2g MyApp

注意:如使用 -XX:+PrintCommandLineFlags 參數或者通過 JMX 查詢,你應該尋找 “InitialHeapSize” 和 “InitialHeapSize” 標志而不是 “Xms” 和 “Xmx”。

-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath

  • 我們可以通過設置 -XX:+HeapDumpOnOutOfMemoryError 讓 JVM 在發生內存溢出時自動的生成堆內存快照。
  • 有了這個參數,當我們不得不面對內存溢出異常的時候會節約大量的時間。默認情況下,堆內存快照會保存在 JVM 的啟動目錄下名為 java_pid.hprof 的文件里(在這里 就是 JVM 進程的進程號)。
  • 也可以通過設置 - XX:HeapDumpPath= 來改變默認的堆內存快照生成路徑, 可以是相對或者絕對路徑。

?注意:堆內存快照文件有可能很龐大,特別是當內存溢出錯誤發生的時候。因此,我們推薦將堆內存快照生成路徑指定到一個擁有足夠磁盤空間的地方。

-XX:OnOutOfMemoryError

當內存溢發生時,我們甚至可以可以執行一些指令,比如發個 E-mail 通知管理員或者執行一些清理工作。通過 - XX:OnOutOfMemoryError 這個參數我們可以做到這一點,這個參數可以接受一串指令和它們的參數。在這里,我們將不會深入它的細節,但我們提供了它的一個例子。在下面的例子中,當內存溢出錯誤發生的時候,我們會將堆內存快照寫到 /tmp/heapdump.hprof 文件并且在 JVM 的運行目錄執行腳本 cleanup.sh

$ java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof -XX:OnOutOfMemoryError="sh ~/cleanup.sh" MyApp

?-XX:PermSize and -XX:MaxPermSize

永久代在堆內存中是一塊獨立的區域,它包含了所有JVM加載的類的對象表示。為了成功運行應用程序,JVM會加載很多類(因為它們依賴于大量的第三方庫,而這又依賴于更多的庫并且需要從里面將類加載進來)這就需要增加永久代的大小。我們可以使用-XX:PermSize?和-XX:MaxPermSize 來達到這個目的。其中-XX:MaxPermSize 用于設置永久代大小的最大值,-XX:PermSize 用于設置永久代初始大小。下面是一個簡單的例子:

$ java -XX:PermSize=128m -XX:MaxPermSize=256m MyApp

請注意,這里設置的永久代大小并不會被包括在使用參數-XX:MaxHeapSize?設置的堆內存大小中。也就是說,通過-XX:MaxPermSize設置的永久代內存可能會需要由參數-XX:MaxHeapSize 設置的堆內存以外的更多的一些堆內存。

-XX:InitialCodeCacheSize and -XX:ReservedCodeCacheSize

JVM一個有趣的,但往往被忽視的內存區域是“代碼緩存”,它是用來存儲已編譯方法生成的本地代碼。

代碼緩存確實很少引起性能問題,但是一旦發生其影響可能是毀滅性的。如果代碼緩存被占滿,JVM會打印出一條警告消息,并切換到interpreted-only 模式:JIT編譯器被停用,字節碼將不再會被編譯成機器碼。

因此,應用程序將繼續運行,但運行速度會降低一個數量級,直到有人注意到這個問題。就像其他內存區域一樣,我們可以自定義代碼緩存的大小。相關的參數是-XX:InitialCodeCacheSize 和-XX:ReservedCodeCacheSize,它們的參數和上面介紹的參數一樣,都是字節值。

-XX:+UseCodeCacheFlushing

如果代碼緩存不斷增長,例如,因為熱部署引起的內存泄漏,那么提高代碼的緩存大小只會延緩其發生溢出。為了避免這種情況的發生,我們可以嘗試一個有趣的新參數:當代碼緩存被填滿時讓JVM放棄一些編譯代碼。通過使用-XX:+UseCodeCacheFlushing 這個參數,我們至少可以避免當代碼緩存被填滿的時候JVM切換到interpreted-only 模式。不過,我仍建議盡快解決代碼緩存問題發生的根本原因,如找出內存泄漏并修復它。

四、新生代垃圾回收

-Xmn

可以使用-Xmn來設定新生代的內存大小,官方建議是整個堆得3/8。

在較老的版本中,還有2個參數-XX:NewSize and -XX:MaxNewSize,而-Xmn則是直接設置一個穩定的新生代大小。

-XX:NewRatio

可以設置新生代和老年代的相對大小。這種方式的優點是新生代大小會隨著整個堆大小動態擴展。參數 -XX:NewRatio 設置老年代與新生代的比例。例如 -XX:NewRatio=3 指定老年代 / 新生代為 3/1。 老年代占堆大小的 3/4,新生代占 1/4 。

如果針對新生代,同時定義絕對值和相對值,絕對值將起作用。下面例子:

$ java -XX:NewSize=32m -XX:MaxNewSize=512m -XX:NewRatio=3 MyApp

此時新生代大小會按照比例和堆大小會動態改變。

以上設置,JVM 會嘗試為新生代分配四分之一的堆大小,但不會小于 32MB 或大于 521MB

在設置新生代大小問題上,使用絕對值還是相對值,不存在通用準則 。如果了解應用的內存使用情況, 設置固定大小的堆和新生代更有利,當然也可以設置相對值。如果對應用的內存使用一無所知,正確的做法是不要設置任何參數,如果應用運行良好。很好,我們不用做任何額外動作。如果遇到性能或 OutOfMemoryErrors,在調優之前,首先需要進行一系列有目的的監控測試,縮小問題的根源。

-XX:SurvivorRatio

參數 -XX:SurvivorRatio-XX:NewRatio 類似,作用于新生代內部區域。默認Eden:S0:S1=8:1:1

-XX:SurvivorRatio 指定伊甸園區 (Eden) 與幸存區大小比例。 例如, -XX:SurvivorRatio=10 表示伊甸園區 (Eden) 是 幸存區 To 大小的 10 倍 (也是幸存區 From 的 10 倍)。 所以, 伊甸園區 (Eden) 占新生代大小的 10/12, 幸存區 From 和幸存區 To 每個占新生代的 1/12 。 注意, 兩個幸存區永遠是一樣大的。

設定幸存區大小有什么作用?

假設幸存區相對伊甸園區 (Eden) 太小, 相應新生對象的伊甸園區 (Eden) 永遠很大空間, 我們當然希望, 如果這些對象在 GC 時全部被回收, 伊甸園區 (Eden) 被清空, 一切正常。

然而, 如果有一部分對象在 GC 中幸存下來, 幸存區只有很少空間容納這些對象。 結果大部分幸存對象在一次 GC 后,就會被轉移到老年代 , 這并不是我們希望的。 考慮相反情況, 假設幸存區相對伊甸園區 (Eden) 太大, 當然有足夠的空間,容納 GC 后的幸存對象。 但是過小的伊甸園區 (Eden), 意味著空間將越快耗盡,增加新生代 GC 次數,這是不可接受的。

總之, 我們希望最小化短命對象晉升到老年代的數量,同時也希望最小化新生代 GC 的次數和持續時間。 我們需要找到針對當前應用的折中方案, 尋找適合方案的起點是 了解當前應用中對象的年齡分布情況。

-XX:+PrintTenuringDistribution

每次新生代GC后,輸出幸存區中的對象的年齡分布。

?例如:

Desired survivor size 75497472 bytes, new threshold 15 (max 15)age 1: 19321624 bytes, 19321624 total age 2: 79376 bytes, 19401000 total age 3: 2904256 bytes, 22305256 total

第一行,表示幸存區75m左右,threshold15(max15),表示老年代閾值是15,最大值也是15

age 1: 19321624bytes ,表示年齡為1是的共有19M左右

age 2:79376 bytes, 表示年齡的共有73KB左右, 后面的total,表示<=當前年齡的總字節數

通過輸出年齡分布,可以更好理解GC

-XX:InitialTenuringThreshold, -XX:MaxTenuringThreshold and -XX:TargetSurvivorRatio

很好理解,設置晉升到老年代的對象年齡閾值

-XX:+NeverTenure and -XX:+AlwaysTenure

這2個參數很極端,不建議使用,除非某些特殊的測試場景。

  • 設置參數 -XX:+NeverTenure,對象永遠不會晉升到老年代。當我們確定不需要老年代時,可以這樣設置。這樣設置風險很大, 并且會浪費至少一半的堆內存。
  • 相反設置參數 -XX:+AlwaysTenure,表示沒有幸存區,所有對象在第一次 GC 時,會晉升到老年代。

五、吞吐量收集相關參數(Parallel Scavenge)

在實踐中我們發現對于大多數的應用領域,評估一個垃圾收集 (GC) 算法如何根據如下兩個標準:

  • 吞吐量越高算法越好
  • 暫停時間越短算法越好
  • 首先讓我們來明確垃圾收集 (GC) 中的兩個術語: 吞吐量 (throughput) 和暫停時間 (pause times)。

    JVM 在專門的線程 (GC threads) 中執行 GC。 只要 GC 線程是活動的,它們將與應用程序線程 (application threads) 爭用當前可用 CPU 的時鐘周期。 簡單點來說,吞吐量是指應用程序線程用時占程序總用時的比例。 例如,吞吐量 99/100 意味著 100 秒的程序執行時間應用程序線程運行了 99 秒, 而在這一時間段內 GC 線程只運行了 1 秒。

    術語” 暫停時間” 是指一個時間段內應用程序線程讓與 GC 線程執行而完全暫停。 例如,GC 期間 100 毫秒的暫停時間意味著在這 100 毫秒期間內沒有應用程序線程是活動的。 如果說一個正在運行的應用程序有 100 毫秒的 “平均暫停時間”,那么就是說該應用程序所有的暫停時間平均長度為 100 毫秒。 同樣,100 毫秒的 “最大暫停時間” 是指該應用程序所有的暫停時間最大不超過 100 毫秒。

    -XX:+UseSerialGC

    指定新生代串行收集器和老年代使用串行收集器

    -XX:+UseParallelGC

    使用Parallel Scavenge+Serail Old(PS MarkSweep)的收集器進行回收

    -XX:+UseParallelOldGC

    使用Parallel Scavenge+Parallel Old進行回收,跟上面相比,就是讓老年代的收集器變為并行的

    -XX:ParallelGCThreads

    通過 - XX:ParallelGCThreads=?我們可以指定并行垃圾收集的線程數量。 例如,-XX:ParallelGCThreads=6 表示每次并行垃圾收集將有 6 個線程執行。

    如果不明確設置該標志,虛擬機將使用基于可用 (虛擬) 處理器數量計算的默認值。 決定因素是由 Java Runtime。availableProcessors() 方法的返回值 N,如果 N<=8,并行垃圾收集器將使用 N 個垃圾收集線程,如果 N>8 個可用處理器,垃圾收集線程數量應為 3+5N/8。

    當 JVM 獨占地使用系統和處理器時使用默認設置更有意義。

    但是,如果有多個 JVM(或其他耗 CPU 的系統) 在同一臺機器上運行,我們應該使用 - XX:ParallelGCThreads 來減少垃圾收集線程數到一個適當的值。

    例如,如果 4 個以服務器方式運行的 JVM 同時跑在在一個具有 16 核處理器的機器上,設置 - XX:ParallelGCThreads=4 是明智的,它能使不同 JVM 的垃圾收集器不會相互干擾。

    -XX:-UseAdaptiveSizePolicy

    吞吐量垃圾收集器提供了一個有趣的 (但常見,至少在現代 JVM 上) 機制以提高垃圾收集配置的用戶友好性。

    這種機制被看做是 HotSpot 在 Java 5 中引入的” 人體工程學” 概念的一部分。 通過人體工程學,垃圾收集器能將堆大小動態變動像 GC 設置一樣應用到不同的堆區域,只要有證據表明這些變動將能提高 GC 性能。

    “提高 GC 性能” 的確切含義可以由用戶通過 - XX:GCTimeRatio 和 - XX:MaxGCPauseMillis(見下文) 標記來指定。 重要的是要知道人體工程學是默認激活的。 這很好,因為自適應行為是 JVM 最大優勢之一。

    不過,有時我們需要非常清楚對于特定應用什么樣的設置是最合適的,在這些情況下,我們可能不希望 JVM 混亂我們的設置。 每當我們發現處于這種情況時,我們可以考慮通過 - XX:-UseAdaptiveSizePolicy 停用一些人體工程學。

    -XX:GCTimeRatio

    通過 - XX:GCTimeRatio=?我們告訴 JVM 吞吐量要達到的目標值。 更準確地說,-XX:GCTimeRatio=N 指定目標應用程序線程的執行時間 (與總的程序執行時間) 達到 N/(N+1) 的目標比值。

    例如,通過 - XX:GCTimeRatio=9 我們要求應用程序線程在整個執行時間中至少 9/10 是活動的 (因此,GC 線程占用其余 1/10)。 基于運行時的測量,JVM 將會嘗試修改堆和 GC 設置以期達到目標吞吐量。

    -XX:GCTimeRatio 的默認值是 99,也就是說,應用程序線程應該運行至少 99% 的總執行時間。

    -XX:MaxGCPauseMillis

    通過 - XX:GCTimeRatio=<value> 告訴 JVM 最大暫停時間的目標值 (以毫秒為單位)。 在運行時,吞吐量收集器計算在暫停期間觀察到的統計數據 (加權平均和標準偏差)。 如果統計表明正在經歷的暫停其時間存在超過目標值的風險時,JVM 會修改堆和 GC 設置以降低它們。 需要注意的是,年輕代和年老代垃圾收集的統計數據是分開計算的,還要注意,默認情況下,最大暫停時間沒有被設置。 如果最大暫停時間和最小吞吐量同時設置了目標值,實現最大暫停時間目標具有更高的優先級。 當然,無法保證 JVM 將一定能達到任一目標,即使它會努力去做。 最后,一切都取決于手頭應用程序的行為。

    當設置最大暫停時間目標時,我們應注意不要選擇太小的值。 正如我們現在所知道的,為了保持低暫停時間,JVM 需要增加 GC 次數,那樣可能會嚴重影響可達到的吞吐量。 這就是為什么對于要求低暫停時間作為主要目標的應用程序 (大多數是 Web 應用程序),我會建議不要使用吞吐量收集器,而是選擇 CMS 收集器。 CMS 收集器是本系列下一部分的主題。

    ?

    六、CMS收集器相關參數

    前面已經對CMS進行了詳細的描述:http://www.cnblogs.com/carl10086/p/6081034.html

    ?CMS是一種真正意義上的并發收集器,讓收集器可以主動給運用程序進行讓步。下面對CMS收集器用到的參數進行簡要說明:

    -XX:+UseConcMarkSweepGC

    該標志首先是激活 CMS 收集器。默認 HotSpot JVM 使用的是并行收集器。

    -XX:UseParNewGC

    當使用 CMS 收集器時,該標志激活年輕代使用多線程并行執行垃圾回收。這令人很驚訝,我們不能簡單在并行收集器中重用 - XX:UserParNewGC 標志,因為概念上年輕代用的算法是一樣的。然而,對于 CMS 收集器,年輕代 GC 算法和老年代 GC 算法是不同的,因此年輕代 GC 有兩種不同的實現,并且是兩個不同的標志。

    注意,當使用 -XX:+UseConcMarkSweepGC 時,-XX:UseParNewGC 會自動開啟。因此,如果年輕代的并行 GC 不想開啟,可以通過設置 -XX:-UseParNewGC 來關掉。

    -XX:+CMSConcurrentMTEnabled

    當該標志被啟用時,并發的 CMS 階段將以多線程執行 (因此,多個 GC 線程會與所有的應用程序線程并行工作)。該標志已經默認開啟,如果順序執行更好,這取決于所使用的硬件,多線程執行可以通過 - XX:-CMSConcurremntMTEnabled 禁用。

    -XX:ConcGCThreads

    標志 - XX:ConcGCThreads=(早期 JVM 版本也叫 -XX:ParallelCMSThreads) 定義并發 CMS 過程運行時的線程數。比如 value=4 意味著 CMS 周期的所有階段都以 4 個線程來執行。盡管更多的線程會加快并發 CMS 過程,但其也會帶來額外的同步開銷。因此,對于特定的應用程序,應該通過測試來判斷增加 CMS 線程數是否真的能夠帶來性能的提升。

    如果還標志未設置,JVM 會根據并行收集器中的 -XX:ParallelGCThreads 參數的值來計算出默認的并行 CMS 線程數。該公式是

    ConcGCThreads = (ParallelGCThreads + 3)/4

    因此,對于 CMS 收集器, -XX:ParallelGCThreads標志不僅影響“stop-the-world”垃圾收集階段,還影響并發階段。

    總之,有不少方法可以配置 CMS 收集器的多線程執行。正是由于這個原因, 建議第一次運行 CMS 收集器時使用其默認設置, 然后如果需要調優再進行測試。只有在生產系統中測量 (或類生產測試系統) 發現應用程序的暫停時間的目標沒有達到 , 就可以通過這些標志應該進行 GC 調優。

    -XX:CMSInitiatingOccupancyFraction

    當堆滿之后,并行收集器便開始進行垃圾收集,例如,當沒有足夠的空間來容納新分配或提升的對象。對于 CMS 收集器,長時間等待是不可取的,因為在并發垃圾收集期間應用持續在運行 (并且分配對象)。因此,為了在應用程序使用完內存之前完成垃圾收集周期,CMS 收集器要比并行收集器更先啟動。

    因為不同的應用會有不同對象分配模式,JVM 會收集實際的對象分配 (和釋放) 的運行時數據,并且分析這些數據,來決定什么時候啟動一次 CMS 垃圾收集周期。為了引導這一過程, JVM 會在一開始執行 CMS 周期前作一些線索查找。該線索由 -XX:CMSInitiatingOccupancyFraction=來設置,該值代表老年代堆空間的使用率。比如,value=75意味著第一次CMS垃圾收集會在老年代被占用75%時被觸發。通常CMSInitiatingOccupancyFraction的默認值為68(之前很長時間的經歷來決定的)。

    -XX:+UseCMSInitiatingOccupancyOnly

    我們用 -XX+UseCMSInitiatingOccupancyOnly 標志來命令 JVM 不基于運行時收集的數據來啟動 CMS 垃圾收集周期。而是,當該標志被開啟時,JVM 通過 CMSInitiatingOccupancyFraction 的值進行每一次 CMS 收集,而不僅僅是第一次。然而,請記住大多數情況下,JVM 比我們自己能作出更好的垃圾收集決策。因此,只有當我們充足的理由 (比如測試) 并且對應用程序產生的對象的生命周期有深刻的認知時,才應該使用該標志。

    -XX:+CMSClassUnloadingEnabled


    相對于并行收集器,CMS 收集器默認不會對永久代進行垃圾回收。如果希望對永久代進行垃圾回收,可用設置標志 -XX:+CMSClassUnloadingEnabled。在早期 JVM 版本中,要求設置額外的標志 - XX:+CMSPermGenSweepingEnabled。注意,即使沒有設置這個標志,一旦永久代耗盡空間也會嘗試進行垃圾回收,但是收集不會是并行的,而再一次進行 Full GC。

    -XX:+CMSIncrementalMode

    ?

    該標志將開啟 CMS 收集器的增量模式。增量模式經常暫停 CMS 過程,以便對應用程序線程作出完全的讓步。因此,收集器將花更長的時間完成整個收集周期。因此,只有通過測試后發現正常 CMS 周期對應用程序線程干擾太大時,才應該使用增量模式。由于現代服務器有足夠的處理器來適應并發的垃圾收集,所以這種情況發生得很少。

    ?

    -XX:+ExplicitGCInvokesConcurrent and -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses

    如今, 被廣泛接受的最佳實踐是避免顯式地調用 GC(所謂的 “系統 GC”),即在應用程序中調用 system.gc()。然而,這個建議是不管使用的 GC 算法的,值得一提的是,當使用 CMS 收集器時,系統 GC 將是一件很不幸的事,因為它默認會觸發一次 Full GC。幸運的是,有一種方式可以改變默認設置。標志 - XX:+ExplicitGCInvokesConcurrent 命令 JVM 無論什么時候調用系統 GC,都執行 CMS GC,而不是 Full GC。第二個標志 - XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses 保證當有系統 GC 調用時,永久代也被包括進 CMS 垃圾回收的范圍內。因此,通過使用這些標志,我們可以防止出現意料之外的”stop-the-world” 的系統 GC。

    -XX:+DisableExplicitGC

    然而在這個問題上… 這是一個很好提到 - XX:+ DisableExplicitGC 標志的機會,該標志將告訴 JVM 完全忽略系統的 GC 調用 (不管使用的收集器是什么類型)。對于我而言,該標志屬于默認的標志集合中,可以安全地定義在每個 JVM 上運行,而不需要進一步思考。

    ?

    轉載于:https://www.cnblogs.com/carl10086/p/6082245.html

    總結

    以上是生活随笔為你收集整理的JVM基础(6)-常用参数总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。