中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解JVM啟動參數

發布時間:2021-10-23 15:43:17 來源:億速云 閱讀:277 作者:柒染 欄目:大數據

怎么理解JVM啟動參數,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

因為Hotspot JDK提供的參數默認值,在小版本之間不斷變化,參數之間也會互相影響。而且,服務器配置不同,都可能影響最后的效果。所以千萬不要迷信網上的某篇文章(包括這篇)里面的參數配置,一切的配置都需要自己親身測試一番才能用。

針對于JVM參數默認值不斷變化,可以使用-XX:+PrintFlagsFinal打印當前環境JVM參數默認值,比如:java -XX:PrintFlagsFinal -version,也可以用java [生產環境參數] -XX:+PrintFlagsFinal –version | grep [待查證的參數]查看具體的參數數據。

這里是一個8G服務器的參數,JDK版本信息如下:

java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)

堆設置

堆內存設置應該算是一個Java程序猿的基本素養,最少也得修改過Xms、Xmx、Xmn這三個參數了。但是一個2G堆大小的JVM,可能總共占用多少內存的?

    堆內存 + 線程數 * 線程棧 + 永久代 + 二進制代碼 + 堆外內存

    2G + 1000 * 1M + 256M + 48/240M + (~2G) = 5.5G (3.5G)
    - 堆內存: 存儲Java對象,默認為物理內存的1/64
    - 線程棧: 存儲局部變量(原子類型,引用)及其他,默認為1M
    - 永久代: 存儲類定義及常量池,注意JDK7/8的區別
    - 二進制代碼:JDK7與8,打開多層編譯時的默認值不一樣,從48到240M
    - 堆外內存: 被Netty,堆外緩存等使用,默認最大值約為堆內存大小

也就是說,堆內存設置為2G,那一個有1000個線程的JVM可能需要占5.5G,在考慮系統占用、IO占用等等各種情況,一臺8G的服務器,也就啟動一個服務了。當然,如果線程數少、并發不高、壓力不大,還是可以啟動多個,而且也可以把堆內存降低。

    -Xms2g 與 -Xmx2g:堆內存大小,第一個是最小堆內存,第二個是最大堆內存,比較合適的數值是2-4g,再大就得考慮GC時間
    -Xmn1g 或 (-XX:NewSize=1g 和 -XX:MaxNewSize=1g) 或 -XX:NewRatio=1:設置新生代大小,JDK默認新生代占堆內存大小的1/3,也就是-XX:NewRatio=2。這里是設置的1g,也就是-XX:NewRatio=1。可以根據自己的需要設置。
    -XX:MetaspaceSize=128m 和 -XX:MaxMetaspaceSize=512m,JDK8的永生代幾乎可用完機器的所有內存,為了保護服務器不會因為內存占用過大無法連接,需要設置一個128M的初始值,512M的最大值保護一下。
    -XX:SurvivorRatio:新生代中每個存活區的大小,默認為8,即1/10的新生代, 1/(SurvivorRatio+2),有人喜歡設小點省點給新生代,但要避免太小使得存活區放不下臨時對象而要晉升到老生代,還是從GC Log里看實際情況了。
    -Xss256k:在堆之外,線程占用棧內存,默認每條線程為1M。存放方法調用出參入參的棧、局部變量、標量替換后的局部變量等,有人喜歡設小點節約內存開更多線程。但反正內存夠也就不必要設小,有人喜歡再設大點,特別是有JSON解析之類的遞歸調用時不能設太小。
    -XX:MaxDirectMemorySize:堆外內存/直接內存的大小,默認為堆內存減去一個Survivor區的大小。
    -XX:ReservedCodeCacheSize:JIT編譯后二進制代碼的存放區,滿了之后就不再編譯。默認開多層編譯240M,可以在JMX里看看CodeCache的大小。

GC設置

目前比較主流的GC是CMS和G1,有大神建議以8G為界。(據說JDK 9默認的是G1)。因為應用設置的內存都比較小,所以選擇CMS收集器。下面的參數也是針對CMS收集器的,等之后如果有需要,再補充G1收集器的參數。
CMS設置

    -XX:+UseConcMarkSweepGC:啟用CMS垃圾收集器
    -XX:CMSInitiatingOccupancyFraction=80 與 -XX:+UseCMSInitiatingOccupancyOnly:兩個參數需要配合使用,否則第一個參數的75只是一個參考值,JVM會重新計算GC的時間。
    -XX:MaxTenuringThreshold=15:對象在Survivor區熬過多少次Young GC后晉升到年老代,默認是15。Young GC是最大的應用停頓來源,而新生代里GC后存活對象的多少又直接影響停頓的時間,所以如果清楚Young GC的執行頻率和應用里大部分臨時對象的最長生命周期,可以把它設的更短一點,讓其實不是臨時對象的新生代長期對象趕緊晉升到年老代。
    -XX:-DisableExplicitGC:允許使用System.gc()主動調用GC。這里需要說明下,有的JVM優化建議是設置-XX:-DisableExplicitGC,關閉手動調用System.gc()。這是應為System.gc()是觸發Full GC,頻繁的Full GC會嚴重影響性能。但是很多NIO框架,比如Netty,會使用堆外內存,如果沒有Full GC的話,堆外內存就無法回收。如果不主動調用System.gc(),就需要等到JVM自己觸發Full GC,這個時候,就可能引起長時間的停頓(STW),而且機器負載也會升高。所以不能夠完全禁止System.gc(),又得縮短Full GC的時間,那就使用-XX:+ExplicitGCInvokesConcurrent或-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses選項,使用CMS收集器來觸發Full GC。這兩個選項需要配合-XX:+UseConcMarkSweepGC使用。
    -XX:+ExplicitGCInvokesConcurrent:使用System.gc()時觸發CMS GC,而不是Full GC。默認是不開啟的,只有使用-XX:+UseConcMarkSweepGC選項的時候才能開啟這個選項。
    -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses:使用System.gc()時,永久代也被包括進CMS范圍內。只有使用-XX:+UseConcMarkSweepGC選項的時候才能開啟這個選項。
    -XX:+ParallelRefProcEnabled:默認為false,并行的處理Reference對象,如WeakReference,除非在GC log里出現Reference處理時間較長的日志,否則效果不會很明顯。
    -XX:+ScavengeBeforeFullGC:在Full GC執行前先執行一次Young GC。
    -XX:+UseGCOverheadLimit: 限制GC的運行時間。如果GC耗時過長,就拋OOM。
    -XX:+UseParallelGC:設置并行垃圾收集器
    -XX:+UseParallelOldGC:設置老年代使用并行垃圾收集器
    -XX:-UseSerialGC:關閉串行垃圾收集器
    -XX:+CMSParallelInitialMarkEnabled 和 -XX:+CMSParallelRemarkEnabled:降低標記停頓
    -XX:+CMSScavengeBeforeRemark:默認為關閉,在CMS remark前,先執行一次minor GC將新生代清掉,這樣從老生代的對象引用到的新生代對象的個數就少了,停止全世界的CMS remark階段就短一些。如果看到GC日志里remark階段的時間超長,可以打開此項看看有沒有效果,否則還是不要打開了,白白多了次YGC。
    -XX:CMSWaitDuration=10000:設置垃圾收集的最大時間間隔,默認是2000。
    -XX:+CMSClassUnloadingEnabled:在CMS中清理永久代中的過期的Class而不等到Full GC,JDK7默認關閉而JDK8打開。看自己情況,比如有沒有運行動態語言腳本如Groovy產生大量的臨時類。它會增加CMS remark的暫停時間,所以如果新類加載并不頻繁,這個參數還是不開的好。

GC日志

GC過程可以通過GC日志來提供優化依據。

    -XX:+PrintGCDetails:啟用gc日志打印功能
    -Xloggc:/path/to/gc.log:指定gc日志位置
    -XX:+PrintHeapAtGC:打印GC前后的詳細堆棧信息
    -XX:+PrintGCDateStamps:打印可讀的日期而不是時間戳
    -XX:+PrintGCApplicationStoppedTime:打印所有引起JVM停頓時間,如果真的發現了一些不知什么的停頓,再臨時加上-XX:+PrintSafepointStatistics -XX: PrintSafepointStatisticsCount=1找原因。
    -XX:+PrintGCApplicationConcurrentTime:打印JVM在兩次停頓之間正常運行時間,與-XX:+PrintGCApplicationStoppedTime一起使用效果更佳。
    -XX:+PrintTenuringDistribution:查看每次minor GC后新的存活周期的閾值
    -XX:+UseGCLogFileRotation 與 -XX:NumberOfGCLogFiles=10 與 -XX:GCLogFileSize=10M:GC日志在重啟之后會清空,但是如果一個應用長時間不重啟,那GC日志會增加,所以添加這3個參數,是GC日志滾動寫入文件,但是如果重啟,可能名字會出現混亂。
    -XX:PrintFLSStatistics=1:打印每次GC前后內存碎片的統計信息

其他參數設置

    -ea:啟用斷言,這個沒有什么好說的,可以選擇啟用,或這選擇不啟用,沒有什么大的差異。完全根據自己的系統進行處理。
    -XX:+UseThreadPriorities:啟用線程優先級,主要是因為我們可以給予周期性任務更低的優先級,以避免干擾客戶端工作。在我當前的環境中,是默認啟用的。
    -XX:ThreadPriorityPolicy=42:允許降低線程優先級
    -XX:+HeapDumpOnOutOfMemoryError:發生內存溢出是進行heap-dump
    -XX:HeapDumpPath=/path/to/java_pid.hprof:這個參數與-XX:+HeapDumpOnOutOfMemoryError共同作用,設置heap-dump時內容輸出文件。
    -XX:ErrorFile=/path/to/hs_err_pid.log:指定致命錯誤日志位置。一般在JVM發生致命錯誤時會輸出類似hs_err_pid.log的文件,默認是在工作目錄中(如果沒有權限,會嘗試在/tmp中創建),不過還是自己指定位置更好一些,便于收集和查找,避免丟失。
    -XX:StringTableSize=1000003:指定字符串常量池大小,默認值是60013。對Java稍微有點常識的應該知道,字符串是常量,創建之后就不可修改了,這些常量所在的地方叫做字符串常量池。如果自己系統中有很多字符串的操作,且這些字符串值比較固定,在允許的情況下,可以適當調大一些池子大小。
    -XX:+AlwaysPreTouch:在啟動時把所有參數定義的內存全部捋一遍。使用這個參數可能會使啟動變慢,但是在后面內存使用過程中會更快。可以保證內存頁面連續分配,新生代晉升時不會因為申請內存頁面使GC停頓加長。通常只有在內存大于32G的時候才會有感覺。
    -XX:-UseBiasedLocking:禁用偏向鎖(在存在大量鎖對象的創建且高度并發的環境下(即非多線程高并發應用)禁用偏向鎖能夠帶來一定的性能優化)
    -XX:AutoBoxCacheMax=20000:增加數字對象自動裝箱的范圍,JDK默認-128~127的int和long,超出范圍就會即時創建對象,所以,增加范圍可以提高性能,但是也是需要測試。
    -XX:-OmitStackTraceInFastThrow:不忽略重復異常的棧,這是JDK的優化,大量重復的JDK異常不再打印其StackTrace。但是如果系統是長時間不重啟的系統,在同一個地方跑了N多次異常,結果就被JDK忽略了,那豈不是查看日志的時候就看不到具體的StackTrace,那還怎么調試,所以還是關了的好。
    -XX:+PerfDisableSharedMem:啟用標準內存使用。JVM控制分為標準或共享內存,區別在于一個是在JVM內存中,一個是生成/tmp/hsperfdata_{userid}/{pid}文件,存儲統計數據,通過mmap映射到內存中,別的進程可以通過文件訪問內容。通過這個參數,可以禁止JVM寫在文件中寫統計數據,代價就是jps、jstat這些命令用不了了,只能通過jmx獲取數據。但是在問題排查是,jps、jstat這些小工具是很好用的,比jmx這種很重的東西好用很多,所以需要自己取舍。這里有個GC停頓的例子。
    -Djava.net.preferIPv4Stack=true:這個參數是屬于網絡問題的一個參數,可以根據需要設置。在某些開啟ipv6的機器中,通過InetAddress.getLocalHost().getHostName()可以獲取完整的機器名,但是在ipv4的機器中,可能通過這個方法獲取的機器名不完整,可以通過這個參數來獲取完整機器名。

大神給出的例子

下面貼上大神給出的例子,可以參考使用,不過還是建議在自己的環境中有針對的驗證之后再使用,畢竟大神的環境和自己的環境還是不同。
性能相關

-XX:-UseBiasedLocking -XX:-UseCounterDecay -XX:AutoBoxCacheMax=20000
-XX:+PerfDisableSharedMem(可選) -XX:+AlwaysPreTouch -Djava.security.egd=file:/dev/./urandom
內存大小相關(JDK7)

-Xms4096m -Xmx4096m -Xmn2048m -XX:MaxDirectMemorySize=4096m
-XX:PermSize=128m -XX:MaxPermSize=512m -XX:ReservedCodeCacheSize=240M

    如果使用jdk8,就把-XX:PermSize=128m -XX:MaxPermSize=512m換成-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m,正如前面所說的,這兩套參數是為了保證安全的,建議還是加上。

CMS GC相關

-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly -XX:MaxTenuringThreshold=6
-XX:+ExplicitGCInvokesConcurrent -XX:+ParallelRefProcEnabled
GC日志相關

-Xloggc:/dev/shm/app-gc.log -XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCDateStamps -XX:+PrintGCDetails
異常日志相關

-XX:-OmitStackTraceInFastThrow -XX:ErrorFile=${LOGDIR}/hs_err_%p.log
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${LOGDIR}/
JMX相關

-Dcom.sun.management.jmxremote.port=${JMX_PORT} -Dcom.sun.management.jmxremote
-Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
參考文章

    Java性能優化指南1.8版,及唯品會的實戰
    Java中的逃逸分析和TLAB以及Java對象分配
    The Four Month Bug: JVM statistics cause garbage collection pauses
 

========================================================

Cassandra,在Linux系統中,默認的JVM啟動參數

-ea
-Xms4096MB
-Xmx4096MB
-Xss128K
-XX:+UseThreadPriorities 
-XX:ThreadPriorityPolicy=42
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=1
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly

-ea 從JDK1.4開始,支持斷言機制,可以用于診斷運行時問題。-ea用來啟動JVM的斷言機制,如果不加packagename和classname,默認運行所有包和類中的斷言。如果希望進行運行某些包和類的斷言,可以類似 -ea:com.foo.util進行設置。

-XX:+UseThreadPriorities  開啟JAVA線程優先級的功能

-XX:ThreadPriorityPolicy JAVA線程優先級的側臉

-XX:+HeapDumpOnOutOfMemoryError 在JVM內存不足而引發程序崩潰時,講內存中的數據導出

-Xss128K 設置線程棧的大小,默認單位為字節,也可以用KB或MB來設置。通常操作系統分配給線程棧的默認大小為1MB。另外,也可以在JAVA CODE中創建線程對象時設置棧的大小,Thread( TheadGroup group, Runnable target, String name, long stackSize)

-XX:+UseParNewGC 縮短JVM GC執行minor收集的時間

-XX:+UseConcMarkSweepGC 縮短JVM GC執行major收集的時間

-XX:+CMSParallelRemarkEnabled 縮短JVM GC執行remark操作的中斷時間

-XX:SurvivorRatio 設置young generation 在 survivor spaces中所占用的大小比例

-XX:MaxTenuringThreshold 表示一個對象如果在survivor spaces移動多少次還沒有被回收就放入老年代

-XX:CMSInitiatingOccupancyFraction 表示老年代占到約百分之多少的時候開始執行CMS操作

-XX:+UseCMSInitiatingOccupancyOnly 這個參數讓JVM只使用CMSInitiatingOccupancyFraction 中定義的值而不用在運行中計算

關于怎么理解JVM啟動參數問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jvm
AI

马边| 千阳县| 明光市| 靖江市| 涞源县| 武乡县| 天柱县| 当雄县| 南昌市| 信丰县| 台南县| 泰州市| 彭州市| 邢台市| 石首市| 乌兰县| 汉沽区| 来凤县| 和静县| 白朗县| 油尖旺区| SHOW| 淄博市| 南岸区| 北宁市| 清河县| 三门峡市| 凤凰县| 天水市| 梁平县| 德兴市| 肥西县| 乌拉特中旗| 廊坊市| 万宁市| 定陶县| 白水县| 卓资县| 田林县| 工布江达县| 新密市|