今天小編給大家分享的是jvm性能調(diào)優(yōu)工具的描述,相信很多人都不太了解,為了讓大家更加了解jvm性能調(diào)優(yōu)工具,所以給大家總結(jié)了以下內(nèi)容,一起往下看吧。一定會有所收獲的哦。
我們提供的服務(wù)有:成都做網(wǎng)站、網(wǎng)站設(shè)計、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、七星關(guān)區(qū)ssl等。為數(shù)千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的七星關(guān)區(qū)網(wǎng)站制作公司
JVM調(diào)優(yōu)目標(biāo):使用較小的內(nèi)存占用來獲得較高的吞吐量或者較低的延遲。
程序在上線前的測試或運行中有時會出現(xiàn)一些大大小小的JVM問題,比如cpu load過高、請求延遲、tps降低等,甚至出現(xiàn)內(nèi)存泄漏(每次垃圾收集使用的時間越來越長,垃圾收集頻率越來越高,每次垃圾收集清理掉的垃圾數(shù)據(jù)越來越少)、內(nèi)存溢出導(dǎo)致系統(tǒng)崩潰,因此需要對JVM進行調(diào)優(yōu),使得程序在正常運行的前提下,獲得更高的用戶體驗和運行效率。
這里有幾個比較重要的指標(biāo):
內(nèi)存占用:程序正常運行需要的內(nèi)存大小。
延遲:由于垃圾收集而引起的程序停頓時間。
吞吐量:用戶程序運行時間占用戶程序和垃圾收集占用總時間的比值。
當(dāng)然,和CAP原則一樣,同時滿足一個程序內(nèi)存占用小、延遲低、高吞吐量是不可能的,程序的目標(biāo)不同,調(diào)優(yōu)時所考慮的方向也不同,在調(diào)優(yōu)之前,必須要結(jié)合實際場景,有明確的的優(yōu)化目標(biāo),找到性能瓶頸,對瓶頸有針對性的優(yōu)化,最后進行測試,通過各種監(jiān)控工具確認調(diào)優(yōu)后的結(jié)果是否符合目標(biāo)。
JVM調(diào)優(yōu)工具
(1)調(diào)優(yōu)可以依賴、參考的數(shù)據(jù)有系統(tǒng)運行日志、堆棧錯誤信息、gc日志、線程快照、堆轉(zhuǎn)儲快照等。
①系統(tǒng)運行日志:系統(tǒng)運行日志就是在程序代碼中打印出的日志,描述了代碼級別的系統(tǒng)運行軌跡(執(zhí)行的方法、入?yún)?、返回值等),一般系統(tǒng)出現(xiàn)問題,系統(tǒng)運行日志是首先要查看的日志。
②堆棧錯誤信息:當(dāng)系統(tǒng)出現(xiàn)異常后,可以根據(jù)堆棧信息初步定位問題所在,比如根據(jù)“java.lang.OutOfMemoryError: Java heap space”可以判斷是堆內(nèi)存溢出;根據(jù)“java.lang.StackOverflowError”可以判斷是棧溢出;根據(jù)“java.lang.OutOfMemoryError: PermGen space”可以判斷是方法區(qū)溢出等。
③GC日志:程序啟動時用 -XX:+PrintGCDetails 和 -Xloggc:/data/jvm/gc.log 可以在程序運行時把gc的詳細過程記錄下來,或者直接配置“-verbose:gc”參數(shù)把gc日志打印到控制臺,通過記錄的gc日志可以分析每塊內(nèi)存區(qū)域gc的頻率、時間等,從而發(fā)現(xiàn)問題,進行有針對性的優(yōu)化。
比如如下一段GC日志:
2018-08-02T14:39:11.560-0800: 10.171: [GC [PSYoungGen: 30128K->4091K(30208K)] 51092K->50790K(98816K), 0.0140970 secs] [Times: user=0.02 sys=0.03, real=0.01 secs] 2018-08-02T14:39:11.574-0800: 10.185: [Full GC [PSYoungGen: 4091K->0K(30208K)] [ParOldGen: 46698K->50669K(68608K)] 50790K->50669K(98816K) [PSPermGen: 2635K->2634K(21504K)], 0.0160030 secs] [Times: user=0.03 sys=0.00, real=0.02 secs] 2018-08-02T14:39:14.045-0800: 12.656: [GC [PSYoungGen: 14097K->4064K(30208K)] 64766K->64536K(98816K), 0.0117690 secs] [Times: user=0.02 sys=0.01, real=0.01 secs] 2018-08-02T14:39:14.057-0800: 12.668: [Full GC [PSYoungGen: 4064K->0K(30208K)] [ParOldGen: 60471K->401K(68608K)] 64536K->401K(98816K) [PSPermGen: 2634K->2634K(21504K)], 0.0102020 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
上面一共是4條GC日志,來看第一行日志,“2018-08-02T14:39:11.560-0800”是精確到了毫秒級別的UTC 通用標(biāo)準(zhǔn)時間格式,配置了“-XX:+PrintGCDateStamps”這個參數(shù)可以跟隨gc日志打印出這種時間戳,“10.171”是從JVM啟動到發(fā)生gc經(jīng)過的秒數(shù)。第一行日志正文開頭的“[GC”說明這次GC沒有發(fā)生Stop-The-World(用戶線程停頓),第二行日志正文開頭的“[Full GC”說明這次GC發(fā)生了Stop-The-World,所以說,[GC和[Full GC跟新生代和老年代沒關(guān)系,和垃圾收集器的類型有關(guān)系,如果直接調(diào)用System.gc(),將顯示[Full GC(System)。接下來的“[PSYoungGen”、“[ParOldGen”表示GC發(fā)生的區(qū)域,具體顯示什么名字也跟垃圾收集器有關(guān),比如這里的“[PSYoungGen”表示Parallel Scavenge收集器,“[ParOldGen”表示Serial Old收集器,此外,Serial收集器顯示“[DefNew”,ParNew收集器顯示“[ParNew”等。再往后的“30128K->4091K(30208K)”表示進行了這次gc后,該區(qū)域的內(nèi)存使用空間由30128K減小到4091K,總內(nèi)存大小為30208K。每個區(qū)域gc描述后面的“51092K->50790K(98816K), 0.0140970 secs”進行了這次垃圾收集后,整個堆內(nèi)存的內(nèi)存使用空間由51092K減小到50790K,整個堆內(nèi)存總空間為98816K,gc耗時0.0140970秒。
④線程快照:顧名思義,根據(jù)線程快照可以看到線程在某一時刻的狀態(tài),當(dāng)系統(tǒng)中可能存在請求超時、死循環(huán)、死鎖等情況是,可以根據(jù)線程快照來進一步確定問題。通過執(zhí)行虛擬機自帶的“jstack pid”命令,可以dump出當(dāng)前進程中線程的快照信息,更詳細的使用和分析網(wǎng)上有很多例,這篇文章寫到這里已經(jīng)很長了就不過多敘述了,貼一篇博客供參考:http://www.cnblogs.com/kongzhongqijing/articles/3630264.html
⑤堆轉(zhuǎn)儲快照:程序啟動時可以使用 “-XX:+HeapDumpOnOutOfMemory” 和 “-XX:HeapDumpPath=/data/jvm/dumpfile.hprof”,當(dāng)程序發(fā)生內(nèi)存溢出時,把當(dāng)時的內(nèi)存快照以文件形式進行轉(zhuǎn)儲(也可以直接用jmap命令轉(zhuǎn)儲程序運行時任意時刻的內(nèi)存快照),事后對當(dāng)時的內(nèi)存使用情況進行分析。
(2)JVM調(diào)優(yōu)工具
①用 jps(JVM process Status)可以查看虛擬機啟動的所有進程、執(zhí)行主類的全名、JVM啟動參數(shù),比如當(dāng)執(zhí)行了JPSTest類中的main方法后(main方法持續(xù)執(zhí)行),執(zhí)行 jps -l可看到下面的JPSTest類的pid為31354,加上-v參數(shù)還可以看到JVM啟動參數(shù)。
3265 32914 sun.tools.jps.Jps 31353 org.jetbrains.jps.cmdline.Launcher 31354 com.danny.test.code.jvm.JPSTest 380
②用jstat(JVM Statistics Monitoring Tool)監(jiān)視虛擬機信息
jstat -gc pid 500 10 :每500毫秒打印一次Java堆狀況(各個區(qū)的容量、使用容量、gc時間等信息),打印10次
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 11264.0 11264.0 11202.7 0.0 11776.0 1154.3 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 11202.7 0.0 11776.0 4037.0 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 11202.7 0.0 11776.0 6604.5 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 11202.7 0.0 11776.0 9487.2 68608.0 36238.7 - - - - 14 0.077 7 0.049 0.126 11264.0 11264.0 0.0 0.0 11776.0 258.1 68608.0 58983.4 - - - - 15 0.082 8 0.059 0.141 11264.0 11264.0 0.0 0.0 11776.0 3076.8 68608.0 58983.4 - - - - 15 0.082 8 0.059 0.141 11264.0 11264.0 0.0 0.0 11776.0 0.0 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149 11264.0 11264.0 0.0 0.0 11776.0 0.0 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149 11264.0 11264.0 0.0 0.0 11776.0 258.1 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149 11264.0 11264.0 0.0 0.0 11776.0 3012.8 68608.0 390.0 - - - - 16 0.084 9 0.066 0.149
jstat還可以以其他角度監(jiān)視各區(qū)內(nèi)存大小、監(jiān)視類裝載信息等,具體可以google jstat的詳細用法。
③用jmap(Memory Map for Java)查看堆內(nèi)存信息
執(zhí)行jmap -histo pid可以打印出當(dāng)前堆中所有每個類的實例數(shù)量和內(nèi)存占用,如下,class name是每個類的類名([B是byte類型,[C是char類型,[I是int類型),bytes是這個類的所有示例占用內(nèi)存大小,instances是這個類的實例數(shù)量:
num #instances #bytes class name ---------------------------------------------- 1: 2291 29274080 [B 2: 15252 19610403: 15252 1871400 4: 18038 721520 java.util.TreeMap$Entry 5: 6182 530088 [C 6: 11391 273384 java.lang.Long 7: 5576 267648 java.util.TreeMap 8: 50 155872 [I 9: 6124 146976 java.lang.String 10: 3330 133200 java.util.LinkedHashMap$Entry 11: 5544 133056 javax.management.openmbean.CompositeDataSupport
執(zhí)行 jmap -dump 可以轉(zhuǎn)儲堆內(nèi)存快照到指定文件,比如執(zhí)行 jmap -dump:format=b,file=/data/jvm/dumpfile_jmap.hprof 3361 可以把當(dāng)前堆內(nèi)存的快照轉(zhuǎn)儲到dumpfile_jmap.hprof文件中,然后可以對內(nèi)存快照進行分析。
參數(shù) | 說明 | 實例 |
---|---|---|
-Xms | 初始堆大小,默認物理內(nèi)存的1/64 | -Xms512M |
-Xmx | 最大堆大小,默認物理內(nèi)存的1/4 | -Xms2G |
-Xmn | 新生代內(nèi)存大小,官方推薦為整個堆的3/8 | -Xmn512M |
-Xss | 線程堆棧大小,jdk1.5及之后默認1M,之前默認256k | -Xss512k |
-XX:NewRatio=n | 設(shè)置新生代和年老代的比值。如:為3,表示年輕代與年老代比值為1:3,年輕代占整個年輕代年老代和的1/4 | -XX:NewRatio=3 |
-XX:SurvivorRatio=n | 年輕代中Eden區(qū)與兩個Survivor區(qū)的比值。注意Survivor區(qū)有兩個。如:8,表示Eden:Survivor=8:1:1,一個Survivor區(qū)占整個年輕代的1/8 | -XX:SurvivorRatio=8 |
-XX:PermSize=n | 永久代初始值,默認為物理內(nèi)存的1/64 | -XX:PermSize=128M |
-XX:MaxPermSize=n | 永久代最大值,默認為物理內(nèi)存的1/4 | -XX:MaxPermSize=256M |
-verbose:class | 在控制臺打印類加載信息 | |
-verbose:gc | 在控制臺打印垃圾回收日志 | |
-XX:+PrintGC | 打印GC日志,內(nèi)容簡單 | |
-XX:+PrintGCDetails | 打印GC日志,內(nèi)容詳細 | |
-XX:+PrintGCDateStamps | 在GC日志中添加時間戳 | |
-Xloggc:filename | 指定gc日志路徑 | -Xloggc:/data/jvm/gc.log |
-XX:+UseSerialGC | 年輕代設(shè)置串行收集器Serial | |
-XX:+UseParallelGC | 年輕代設(shè)置并行收集器Parallel Scavenge | |
-XX:ParallelGCThreads=n | 設(shè)置Parallel Scavenge收集時使用的CPU數(shù)。并行收集線程數(shù)。 | -XX:ParallelGCThreads=4 |
-XX:MaxGCPauseMillis=n | 設(shè)置Parallel Scavenge回收的最大時間(毫秒) | -XX:MaxGCPauseMillis=100 |
-XX:GCTimeRatio=n | 設(shè)置Parallel Scavenge垃圾回收時間占程序運行時間的百分比。公式為1/(1+n) | -XX:GCTimeRatio=19 |
-XX:+UseParallelOldGC | 設(shè)置老年代為并行收集器ParallelOld收集器 | |
-XX:+UseConcMarkSweepGC | 設(shè)置老年代并發(fā)收集器CMS | |
-XX:+CMSIncrementalMode | 設(shè)置CMS收集器為增量模式,適用于單CPU情況。 |
以上就是jvm性能調(diào)優(yōu)工具的描述的詳細內(nèi)容了,看完之后是否有所收獲呢?如果想了解更多相關(guān)內(nèi)容,歡迎來創(chuàng)新互聯(lián)行業(yè)資訊!