Java中JVM常用參數(shù)配置教程(提供配置示例)
前言
在實際開發(fā)和部署中一個合格的碼農(nóng)都會對JVM的一些參數(shù)做合理的配置,比如內(nèi)存配置參數(shù)、GC策略配置參數(shù)、日志配置參數(shù)、異常信息參數(shù)等,本文會列出一些常用的JVM參數(shù)以及通過一些例子演示配置后的效果。
PS:本文使用JDK1.8
一、內(nèi)存參數(shù)配置
// 設(shè)置JVM使Server模式,特點是啟動速度較慢,但運行時性能和內(nèi)存管理效率很高,適用于生產(chǎn)環(huán)境。在具有64位能力的JDK環(huán)境下默認(rèn)啟用該模式。 -server // 設(shè)置元空間最大值, 默認(rèn)是-1, 即不限制, 或者說只受限于本地內(nèi)存大小,如果超過這個值會內(nèi)存溢出。 -XX:MaxMetaspaceSize=256m // 指定元空間觸發(fā)Fullgc的初始閾值(元空間無固定初始大小), 以字節(jié)為單位,默認(rèn)是21M,達(dá)到該值就會觸發(fā)full gc進(jìn)行類型卸載, 同時收集器會對該值進(jìn)行調(diào)整: 如果釋放了大量的空間, 就適當(dāng)降低該值; 如果釋放了很少的空間, 那么在不超過-XX:MaxMetaspaceSize(如果設(shè)置了的話) 的情況下, 適當(dāng)提高該值。這個跟早期jdk版本的-XX:PermSize參數(shù)意思不一樣,-XX:PermSize代表永久代的初始容量。 // 觸發(fā)一次元空間Full GC后就會重新計算該值,建議設(shè)置成和最大內(nèi)存一致 -XX:MetaspaceSize=256m // 設(shè)置最大堆內(nèi)存,默認(rèn)是物理內(nèi)存的1/4,內(nèi)存的單位可以是m g,并且不區(qū)分大小寫 -Xmx2g 或者 -XX:MaxHeapSize=2048m // 設(shè)置初始值堆內(nèi)存,默認(rèn)是物理內(nèi)存的1/64,內(nèi)存的單位可以是m g,并且不區(qū)分大小寫 -Xms2g 或者 -XX:InitialHeapSize=2048m // 設(shè)置年輕代內(nèi)存大小,默認(rèn)和老年代1\2,-XX:NewSize初始化年輕代大小 -XX:MaxNewSize最大年輕代大小 -Xmn1g 或者 -XX:NewSize=1g -XX:MaxNewSize=1g // 設(shè)置每個線程的堆棧大小 默認(rèn)是1024k,這個是最大內(nèi)存并不是開啟一個線程馬上就會消耗這么多內(nèi)存 -Xss512k 或者 -XX:ThreadStackSize=512k // 年輕代占用堆比例(如果有配置-Xmn,那么會以-Xmn配置為準(zhǔn)) // 默認(rèn) -XX:NewRatio=2新生代占1,老年代占2,年輕代占整個堆的1/3 // 假如 -XX:NewRatio=4新生代占1,老年代占4,年輕代占整個堆的1/5 NewRatio值就是設(shè)置老年代的占比,剩下的1給新生代 -XX:NewRatio=2 // 用來設(shè)置新生代中eden空間和from/to空間的比例.含義:-設(shè)置為8代表 eden使用80%的新生代內(nèi)存 from和to各用10%,默認(rèn)為8 -XX:SurvivorRatio=8 // 禁用Survivor區(qū)自適應(yīng)策略默認(rèn)是開啟的,如果不關(guān)閉這個配置新生代eden區(qū)和s0 s1區(qū)會在gc后自動調(diào)整大小,如果設(shè)置了-XX:SurvivorRatio也只有在沒有GC之前有效只要GC后就會重新動態(tài)計算 -XX:-UseAdaptiveSizePolicy // 擴張堆內(nèi)存的時機 // 堆內(nèi)存使用率大于70時擴張堆內(nèi)存,如果最大堆內(nèi)存=初始堆內(nèi)存時該參數(shù)無效,默認(rèn)值70 -XX:MaxHeapFreeRatio=70 // 縮小堆內(nèi)存的時機 // 堆內(nèi)存使用率小于40時縮減堆內(nèi)存,如果最大堆內(nèi)存=初始堆內(nèi)存時該參數(shù)無效,默認(rèn)值40 -XX:MinHeapFreeRatio=40 // 字符串常量池hash桶大小 類似于HashTable,最小值1009 默認(rèn)60013 不可動態(tài)擴容 -XX:StringTableSize=60013 // 設(shè)置直接內(nèi)存大小,NIO(Non-blocking I/O)中通過ByteBuffer等對象分配的堆外內(nèi)存 // 默認(rèn)情況下,直接內(nèi)存的大小可能會與Java堆的最大值 (-Xmx) 相同 -XX:MaxDirectMemorySize=512m
二、垃圾收集器配置
// 配置使用Serial單線程垃圾收集器,虛擬機運行在Client模式下的默認(rèn)值 // 新生代使用Serial 老年代則使用SerialOld -XX:+UseSerialGC // 配置使用ParNew垃圾收集器 // 新生代使用ParNew 老年代則使用Serial Old -XX:+UseParNewGC // 配置使用Parallel Scavenge垃圾收集器,虛擬機運行在Server模式下的默認(rèn)值 // 新生代使用Parallel Scavenge 老年代使用Parallel Old收集器 -XX:+UseParallelGC // 配置使用Parallel Old垃圾收集器 // 新生代使用Parallel Scavenge 老年代使用Parallel Old收集器 -XX:+UseParallelOldGC // 配置使用CMS垃圾收集器 // 新生代使用ParNew 老年代使用CMS+Serial Old收集器 -XX:+UseConcMarkSweepGC // 配置使用G1垃圾收集器 -XX:+UseG1GC
可以通過jinfo -flags 進(jìn)程號
查看對應(yīng)Java程序啟動參數(shù),我本地使用的JDK1.8默認(rèn)使用的ParallelGC
三、GC策略配置
3.1、基礎(chǔ)通用配置
// GC停頓時間,垃圾收集器會嘗試用各種手段達(dá)到這個時間,比如減小年輕代 -XX:MaxGCPauseMillis // 新生代晉升老年代閾值 默認(rèn)是15 不同回收算法不同 -XX:MaxTenuringThreshold=15 // 對象動態(tài)年齡判斷默認(rèn)50% 當(dāng)一批對象大小>=survivor區(qū)的50%時這批對象會直接放入老年代 -XX:TargetSurvivorRatio=50 // 默認(rèn)值是0沒有限制 大于這個值的參數(shù)直接在老年代分配 // 這樣做的目的是避免在Eden區(qū)和兩個Survivor區(qū)之間發(fā)生大量的內(nèi)存復(fù)制 ‐XX:PretenureSizeThreshold=1m // 忽略手動調(diào)用GC, System.gc()的調(diào)用就會變成一個空調(diào)用,完全不觸發(fā)GC -XX:+DisableExplicitGC // 內(nèi)存頁的大小 -XX:LargePageSizeInBytes=128m // 設(shè)定GMT區(qū)域,避免CentOS坑爹的時區(qū)設(shè)置 -Duser.timezone=GMT+8 // FullGC 前執(zhí)行MinorGC 默認(rèn)是開啟的 -XX:+ScavengeBeforeFullGC
3.2、Parallel 和 Parallel Old 常用參數(shù)配置
// 調(diào)整垃圾回收的時間和總時間的占比 公式 1/(1+ratio) ratio默認(rèn)是99,100分鐘運行時間默認(rèn)不能超過1分鐘的GC時間,ratio一般設(shè)置為19 -XX:GCTimeRatio=99 // GC最大暫停毫秒數(shù) 默認(rèn)是200毫秒 和-XX:+GCTimeRatio有沖突,堆內(nèi)存小回收速度才會快,而-XX:+GCTimeRatio需要保證一定時間內(nèi)GC時間不能超過一個臨界值需要增加內(nèi)存才能減小GC時間比,需要找到一個兩個參數(shù)的合理值 -XX:MaxGCPauseMillis=200ms // 設(shè)置垃圾回收線程數(shù)量 默認(rèn)是CUP內(nèi)核數(shù)量 -XX:ParallelGCThreads=4
3.3、CMS 常用參數(shù)配置
// GC最大暫停毫秒數(shù) 默認(rèn)是200毫秒 -XX:MaxGCPauseMillis=200ms // 為了加快此階段處理速度,減少停頓時間,可以開啟初始標(biāo)記并行化 -XX:+CMSParallelInitialMarkEnabled // CMS并行線程數(shù)量,并行線程用于執(zhí)行 CMS 垃圾回收器的并行階段,如初始標(biāo)記階段和重新標(biāo)記階段 // 默認(rèn)值為系統(tǒng)的邏輯處理器數(shù)量減1,目的是為了保留一個處理器用于應(yīng)用程序線程 -XX:ParallelCMSThreads=3 // CMS并發(fā)線程數(shù)量,并發(fā)線程用于執(zhí)行 CMS 垃圾回收器的并發(fā)階段,如初始標(biāo)記階段、并發(fā)標(biāo)記階段和并發(fā)清理階段。 // 默認(rèn)值為系統(tǒng)的邏輯處理器數(shù)量減1,目的是為了保留一個處理器用于應(yīng)用程序線程 -XX:ConcGCThreads=3 // 執(zhí)行CMS的內(nèi)存占比 percent=80 當(dāng)我的老年代內(nèi)存達(dá)到80%觸發(fā)垃圾回收 默認(rèn)是92% 應(yīng)為CMS采用標(biāo)記清除需要給浮動垃圾(在最后一步并發(fā)清除時其它沒有被標(biāo)記的垃圾遺留)預(yù)留空間 -XX:CMSInitiatingOccupancyFraction=percent // 該參數(shù)需要配合XX:CMSInitiatingOccupancyFraction使用,只使用設(shè)定的回收閾值(-XX:CMSInitiatingOccupancyFraction設(shè) 定的值),如果不指定,JVM僅在第一次使用設(shè)定值,后續(xù)則會自動調(diào)整 -XX:+UseCMSInitiatingOccupancyOnly // 重新標(biāo)記階段前提前進(jìn)行一次新生代GC,因為重新標(biāo)記也會判斷新生代對象是否引用老年代對象,有些時候新生代對象已經(jīng)沒有被GC root對象引用但是還沒有GC時,重新標(biāo)記會掃描到新生代對象并且保留新生代對象引用的老年代對象,默認(rèn)關(guān)閉false -XX:CMSScavengeBeforeRemark=true // 執(zhí)行完Full GC后對內(nèi)存空間進(jìn)行壓縮整理 默認(rèn)開啟 -XX:+UseCMSCompactAtFullGollection // 設(shè)置在執(zhí)行多少次Full GC后對內(nèi)存空間進(jìn)行壓縮整理 默認(rèn)0次,只要觸發(fā)Full GC就會進(jìn)行內(nèi)存壓縮 -XX:CMSFullGCsBeforeCompaction=0 // 垃圾回收時是否同時卸載不用的class信息,默認(rèn)關(guān)閉 -XX:+CMSClassUnloadingEnabled
3.4、G1 常用參數(shù)配置
// 指定分區(qū)大小(1MB~32MB,且必須是2的N次冪),不設(shè)置默認(rèn)會根據(jù)堆大小分配 // 堆內(nèi)存為1G默認(rèn)1024個1MB分區(qū)、堆內(nèi)存為2G默認(rèn)2048個1MB分區(qū)、堆內(nèi)存為4G默認(rèn)2048個2MB分區(qū)、堆內(nèi)存為4G默認(rèn)2048個2MB分區(qū)、堆內(nèi)存為6G默認(rèn)6144個1MB分區(qū)、堆內(nèi)存為8G默認(rèn)2048個4MB分區(qū)、以此類推 -XX:G1HeapRegionSize=2m // 目標(biāo)暫停時間(默認(rèn)200ms) -XX:MaxGCPauseMillis=200ms // 新生代內(nèi)存初始空間(默認(rèn)整堆5%) // PS: 因為JDK版本問題,在啟動時可能會出現(xiàn) "Error: VM option 'G1NewSizePercent' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions." // 如果出現(xiàn)上述問題,在啟動參數(shù)中添加-XX:+UnlockExperimentalVMOptions即可 -XX:G1NewSizePercent=5 // 新生代內(nèi)存最大空間 (默認(rèn)整堆60%) -XX:G1MaxNewSizePercent=60 // Survivor區(qū)的填充容量(默認(rèn)50%),Survivor區(qū)域里的一批對象(年齡1+年齡2+年齡n的多個 年齡對象)總和超過了Survivor區(qū)域的50%,此時就會把年齡n(含)以上的對象都放入老年代 -XX:TargetSurvivorRatio=50 // 最大年齡閾值(默認(rèn)15) -XX:MaxTenuringThreshold=15 // 老年代占用空間達(dá)到整堆內(nèi)存閾值(默認(rèn)45%),則執(zhí)行新生代和老年代的混合收集(MixedGC) -XX:InitiatingHeapOccupancyPercent=45 // region中的存活對象低于這個值時才會回收該region,如果超過這個值,存活對象過多,回收的的意義不大(默認(rèn)65%)。 -XX:G1MixedGCLiveThresholdPercent=65 // 在一次回收過程中指定做幾次篩選回收(默認(rèn)8次),在最后一個篩選回收階段可以回收一會,然后暫?;厥?,恢復(fù)系統(tǒng)運行,一會再開始回收,這樣可以讓系統(tǒng)不至于單次停頓時間過長。 -XX:G1MixedGCCountTarget=8 // gc過程中空出來的region是否充足閾值,在混合回收的時候,對Region回收都是基于復(fù)制算法進(jìn)行的,都是把要回收的Region里的存活對象放入其他Region,然后這個Region中的垃圾對象全部清理掉,這樣的話在回收過程就會不斷空出來新的Region,一旦空閑出來的Region數(shù)量達(dá)到了堆內(nèi)存的5%,此時就會立即停止混合回收,意味著本次混合回收就結(jié)束了(默認(rèn)5%)。 -XX:G1HeapWastePercent=5
四、GC日志配置
// 設(shè)置日志目錄和日志名稱 -Xloggc:/data/logs/gc-%t.log // 開啟滾動生成日志 默認(rèn)關(guān)閉 -XX:+UseGCLogFileRotation // 滾動GC日志文件數(shù),默認(rèn)0不滾動,保留最多5個日志文件 -XX:NumberOfGCLogFiles=5 // GC文件滾動大小,需開啟UseGCLogFileRotation,每個文件最大為20MB -XX:GCLogFileSize=20M // 在進(jìn)行GC的前后打印出堆的信息 -XX:+PrintHeapAtGC // 打印新生代晉升詳情 -XX:+PrintTenuringDistribution // 打印字符串常量池堆信息 -XX:+PrintStringTableStatistics // 打印GC信息 -verbose:gc // 打印GC詳細(xì)信息 -XX:+PrintGCDetails // 輸出GC的時間戳(以基準(zhǔn)時間的形式) -XX:+PrintGCTimeStamps // 輸出GC的時間戳(以日期的形式,如 2013-05-04T21:53:59.234+0800) -XX:+PrintGCDateStamps // 打印當(dāng)前JVM參數(shù)信息 建議在每個程序中都添加上 -XX:+PrintCommandLineFlags // 產(chǎn)生GC的原因(默認(rèn)開啟) -XX:+PrintGCCause
五、dump 日志參數(shù)配置
5.1、OutOfMemory異常時生成dump文件
// 默認(rèn)關(guān)閉 // 可以通過jinfo -flag [+|-]HeapDumpOnOutOfMemoryError <pid> 或 jinfo -flag HeapDumpOnOutOfMemoryError=<value> <pid> 來動態(tài)開啟或設(shè)置值 -XX:+HeapDumpOnOutOfMemoryError // 設(shè)置文件存儲路徑 // 當(dāng)HeapDumpOnOutOfMemoryError開啟的時候,dump文件的保存路徑,默認(rèn)為工作目錄下的,可以通過配置指定保存路徑 -XX:HeapDumpPath=/data/dump/jvm.hprof
5.2、發(fā)生Full GC時生成dump文件
不推薦開啟會增加整體停頓時間
// 在Full GC前dump -XX:+HeapDumpBeforeFullGC // 在Full GC后dump -XX:+HeapDumpAfterFullGC // 設(shè)置Dump保存的路徑 -XX:HeapDumpPath=/data/dump/jvm.hprof
六、其它參數(shù)配置
// JVM自身故障導(dǎo)致進(jìn)程奔潰時,會有一個日志文件生成,它包含了導(dǎo)致crash的重要信息,通過分析文件來查找crash原因 -XX:ErrorFile=/data/logs/error.log // JDK1.6開始,默認(rèn)server模式下開啟了這個參數(shù),意為當(dāng)jvm檢測到程序在重復(fù)拋一個異常 // 在執(zhí)行若干次后會將異常吞掉,這里的若干次在jdk1.7測得是20707。即執(zhí)行20707次后,stackTrace 長度會為0。有時這不利于我們排錯,通過指定OmitStackTraceInFastThrow,可禁用這功能 -XX:-OmitStackTraceInFastThrow
七、配置示例
需要配置的參數(shù)信息
// 配置新生代使用Parallel Scavenge 老年代將會使用Parallel Old收集器 -XX:+UseParallelOldGC // 配置元空間最大內(nèi)存和初始內(nèi)存 -XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=256m // 配置最大堆內(nèi)存、初始內(nèi)存、新生代占用內(nèi)存 -Xmx512m -Xms512m -Xmn256m // 配置關(guān)閉動態(tài)調(diào)整新生代eden和from to大小比例 -XX:-UseAdaptiveSizePolicy // 配置忽略手動調(diào)用GC和時區(qū) -XX:+DisableExplicitGC -Duser.timezone=GMT+8 // 配置開啟記錄OOM Dump信息和存儲地址 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./jvm.hprof // 配置打印當(dāng)前JVM參數(shù)信息 -XX:+PrintCommandLineFlags // 配置開啟GC日志輸出 -verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gc-%t.log // 配置關(guān)閉重復(fù)多次拋同一個異常不輸出 -XX:-OmitStackTraceInFastThrow // 配置JVM自身故障導(dǎo)致宕機時日志輸出目錄 -XX:ErrorFile=./error.log
7.1、在IDEA中配置JVM參數(shù)
- 配置參數(shù)(注意文件的輸出目錄,我這里會直接輸出在當(dāng)前目錄)
-XX:+UseParallelOldGC -XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=256m -Xmx20m -Xms20m -Xmn10m -XX:-UseAdaptiveSizePolicy -XX:+DisableExplicitGC -Duser.timezone=GMT+8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./jvm.hprof -XX:+PrintCommandLineFlags -verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gc-%t.log -XX:-OmitStackTraceInFastThrow -XX:ErrorFile=./error.log
- 配置流程
7.2、通過 Java -jar 啟動配置
# 應(yīng)用配置示例 nohup java -XX:+UseParallelOldGC -XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=256m -Xmx512m -Xms512m -Xmn256m -XX:-UseAdaptiveSizePolicy -XX:+DisableExplicitGC -Duser.timezone=GMT+8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./jvm.hprof -XX:+PrintCommandLineFlags -verbose:gc -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gc-%t.log -XX:-OmitStackTraceInFastThrow -XX:ErrorFile=./error.log -jar app.jar > app.log 2>&1 &
總結(jié)
到此這篇關(guān)于Java中JVM常用參數(shù)配置的文章就介紹到這了,更多相關(guān)Java JVM常用參數(shù)配置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot整合Sa-Token實現(xiàn)登錄認(rèn)證的示例代碼
本文主要介紹了SpringBoot整合Sa-Token實現(xiàn)登錄認(rèn)證的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01SpringMVC4+MyBatis+SQL Server2014實現(xiàn)數(shù)據(jù)庫讀寫分離
這篇文章主要介紹了SpringMVC4+MyBatis+SQL Server2014實現(xiàn)讀寫分離,需要的朋友可以參考下2017-04-04java批量采集豌豆莢網(wǎng)站Android應(yīng)用圖標(biāo)和包名
這篇文章主要介紹了java批量采集豌豆莢網(wǎng)站Android應(yīng)用圖標(biāo)和包名,主要用在做主題時替換這些常見應(yīng)用的圖片,需要的朋友可以參考下2014-06-06Spring Boot集成Mybatis的實例代碼(簡潔版)
這篇文章主要介紹了Spring Boot集成Mybatis簡潔版的教程,需要的朋友可以參考下2018-02-02Intellij IDEA Debug調(diào)試技巧(小結(jié))
這篇文章主要介紹了Intellij IDEA Debug調(diào)試技巧(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10解析SpringBoot中@Autowire注解的實現(xiàn)原理
在開發(fā)Java項目時,依賴注入是一種常見的實現(xiàn)方式,SpringBoot框架通過@Autowired注解來實現(xiàn)依賴注入的功能,本文將介紹SpringBoot中 Autowired注解實現(xiàn)的原理2023-06-06