調什么
JVM調優(yōu):1道川、是想調什么,2括改、能調什么(只能調開放接口的襟己,很多東西不一定開放接口給你調整),綜合考慮只有如下兩個方面:
- 內存方面
- 線程方面
內存方面
JVM需要的內存總大小厦画。
各塊內存分配疮茄,新生代、存活區(qū)根暑、老年代力试。
選擇合適的垃圾回收算法、控制GC停頓次數(shù)和時間排嫌。
解決內存泄漏的問題畸裳,輔助代碼優(yōu)化。
內存熱點:檢查哪些對象在系統(tǒng)中數(shù)量最大淳地,輔助代碼優(yōu)化怖糊。
線程方面
死鎖檢查,輔助代碼優(yōu)化颇象。
Dump線程詳細信息:查看線程內部運行情況伍伤,查找競爭線程,輔助代碼優(yōu)化夯到。
CPU熱點:檢查系統(tǒng)哪些方法占用了大量CPU時間嚷缭,輔助代碼優(yōu)化。
如何調優(yōu)
監(jiān)控JVM的狀態(tài),主要是內存阅爽、線程路幸、代碼、I/O幾部分付翁。
分析結果简肴,判斷是否需要優(yōu)化。
調整:垃圾回收算法和內存分配百侧,修改并優(yōu)化代碼砰识。
不斷的重復監(jiān)控、分析和調整佣渴,直至找到優(yōu)化的平衡點辫狼。
JVM調優(yōu)的目標
GC的時間足夠小。
GC的次數(shù)足夠小辛润。
將轉移到老年代的對象數(shù)量降低到最小膨处。
減少Full GC的執(zhí)行時間。
發(fā)生Full GC的間隔時間足夠的長砂竖。
常見的調優(yōu)策略
減少創(chuàng)建對象的數(shù)量真椿。
減少使用全局變量和大對象。
調整新生代乎澄、老年代的大小到最合適突硝。
選擇合適的GC收集器,并設置合理的參數(shù)置济。
JVM調優(yōu)冷思考
多數(shù)的Java應用不需要在服務器上進行GC優(yōu)化解恰。
多數(shù)導致GC問題的Java應用,都不是因為參數(shù)設置錯誤舟肉,而是代碼問題修噪。
在應用上線前,先考慮將機器的JVM參數(shù)設置到最優(yōu)(最合適)路媚。
JVM優(yōu)化是到最后不得已才采用的手段黄琼。
在實例使用中,分析JVM情況優(yōu)化代碼比優(yōu)化JVM本身要多得多整慎。
-
如下情況通常不用優(yōu)化:
- Minor GC執(zhí)行時間不到50ms脏款。
- Minor GC執(zhí)行不頻繁,約10秒甚至更差時間才執(zhí)行一次裤园。
- Full GC執(zhí)行時間不到1s撤师。
- Full GC執(zhí)行頻率不算頻繁,不低于10分鐘1次拧揽。
JVM調優(yōu)經(jīng)驗
要注意32位和64為操作系統(tǒng)的區(qū)別剃盾,32位操作系統(tǒng)支持的內存理論上最多為2的32次方4G腺占,而64位操作系統(tǒng)理論的尋址能力為2的64次方,內存識別的多少是和計算機cpu的尋址有關痒谴。
注意client模式和Server模式的選擇衰伯。
要想GC的時間小必須要一個更小的堆,而要保證GC次數(shù)足夠少积蔚,又必須要保證一個更大的堆意鲸,這兩個是有沖突的,只能取其平衡尽爆。
針對JVM堆的設置怎顾,一般可以通過-Xms -Xmx限定其最小、最大值漱贱,為了防止垃圾收集器在最小槐雾、最大之間收縮堆而產(chǎn)生額外的時間,通常把最大饱亿、最小設置為相同的值蚜退。
新生代和老年代將根據(jù)默認的比例(1:2)分配內存堆闰靴,可以通過調整二者之間的比率NewRadio來調整彪笼,也可以通過-XX:newSize -XX:MaxNewSize來設置其絕對大小,同樣蚂且,為了防止新生的堆收縮配猫,通常會把-XX:newSize -XX:MaxNewSize設置為同樣大小。
合理規(guī)劃新生代和老年代的大小杏死。
如果應用存在大量的臨時對象泵肄,應該選擇更大的新生代;如果存在相對較多的持久對象淑翼,老年代應該適當增大腐巢。在抉擇時應該本著Full GC盡量少的原則,讓老年代盡量緩存常用對象玄括,JVM的默認比例1:2也是這個道理冯丙。
通過觀察應用一段時間,看其在峰值時老年代會占多少內存遭京,在不影響Full GC的前提下胃惜,根據(jù)實際情況加大新生代,但應該給老年代至少預留1/3的增長空間哪雕。
線程堆棧的設置:每個線程默認會開啟1M的堆棧船殉,用于存放棧幀、調用參數(shù)斯嚎、局部變量等利虫,對大多數(shù)應用而言這個默認值太大了挨厚,一般256K就足夠了。在內存不變的情況下糠惫,減少每個線程的堆棧幽崩,可以產(chǎn)生更多的線程。
內存泄漏
-
內存泄漏導致系統(tǒng)崩潰前的一些現(xiàn)象寞钥,比如:
- 1慌申、每次垃圾回收時間越來越長,F(xiàn)ull GC時間也延長到好幾秒理郑。
- 2蹄溉、Full GC的次數(shù)越來越多,最頻繁時隔不到1分鐘就進行一次Full GC您炉。
- 3柒爵、老年代的內存越來越大,并且每次Full GC后老年代沒有內存被釋放赚爵。
- 4棉胀、老年代堆空間被占滿的情況。
內存泄漏的解決方式:一般就是根據(jù)垃圾回收前后情況對比冀膝,同時根據(jù)對象引用情況分析唁奢,輔助去查找泄漏點。
堆棧溢出的情況窝剖,通常會拋出java.lang.StackOverflowError麻掸,一般就是遞歸調用沒退出,或者循環(huán)調用導致赐纱。
調優(yōu)步驟
重點是調優(yōu)的過程脊奋、方法和思路
內存調整、數(shù)據(jù)庫連接調整疙描、內存泄漏查找等
通過JMC錄制JFR飛行記錄
- 1诚隙、查看CPU的占用率
- 2、內存的分配和使用量
- 3起胰、垃圾收集的執(zhí)行頻率久又、暫停時間、垃圾收集區(qū)域
- 4待错、文件I/O籽孙、套接字I/O,查看遠程I/O阻塞時間
-
一般信息火俄,堆使用量犯建、CPU總體占用率、GC暫停時間是非常重要的三個指標瓜客,對于Java應用而言适瓦,GC暫停時間是最值得關注的指標竿开。
-
通過內存信息,我們可以清晰的看到垃圾收集器的類型玻熙,垃圾收集的暫停時間否彩,包括最短暫停時間、平均暫停時間嗦随、最長暫停時間列荔,以及更為重要的垃圾收集頻率(垃圾收集的周期及STW時長)。
-
代碼分析是Java性能分析重點枚尼,通過代碼分析贴浙,我們可以清楚的知道系統(tǒng)運行時,哪些類及方法被高頻率的調用署恍。
-
熱點方法崎溃,通過查看熱點方法調用棧,我們可以清晰的了解到系統(tǒng)的主要計算資源消耗情況盯质。
-
通過調用樹袁串,我們能以模塊化的方式直觀的看到系統(tǒng)運行狀態(tài)。
-
通過線程概述報告呼巷,我們可以得知CPU占用率的分布(系統(tǒng)占用率囱修、應用程序+JVM占用率)和活動線程數(shù),對于CPU占用率而言朵逝,應用程序應該占用99%的計算資源蔚袍,而活動線程數(shù)應該控制在合理范圍內(具體看應用)。
-
熱點線程一欄配名,詳細列出了熱點線程的數(shù)量及詳情,通過詳情晋辆,我們可以得知線程的執(zhí)行情況渠脉。
-
線程爭用是解決應用性能最為關鍵的部分,在應用上線初期瓶佳,我們可以通過解決線程爭用初步實現(xiàn)系統(tǒng)性能的巨大提升芋膘。上圖中的爭用為GC導致,具體是由于使用G1時霸饲,設置的GC預期暫停時間過短導致的为朋。
-
IO作為系統(tǒng)的基礎指標,IO過高會導致系統(tǒng)性能急劇下降厚脉,避免過度打印日志和生成大文件可以避免系統(tǒng)IO過高導致的性能問題习寸。
通過VisualVM查詢實時的虛擬機信息
-
1、查看監(jiān)視界面傻工,可以看到cup運行情況霞溪、堆的使用情況孵滞、類的情況以及線程的動態(tài)情況。
-
2鸯匹、查看線程坊饶,可以看到所有的線程的情況,是運行殴蓬、休眠匿级、等待、駐留染厅、監(jiān)視等情況根蟹。
也可以點擊右上角Dump按鈕,將線程的信息導出糟秘,其實就是執(zhí)行的jstack命令简逮。
- 3、查看抽樣器尿赚,抽樣器可以對CPU散庶、內存在一段時間內進行抽樣,
- A凌净、CPU監(jiān)控:查看熱點方法和各個方法占用CPU時間及其比例悲龟。
-
B、內存監(jiān)控:每個線程分配內存冰寻。
抽樣cpu
- 4须教、添加插件Visual GC,利用Visual GC分析虛擬機內存區(qū)域斩芭。
- A轻腺、內存大小分情況
- B、主要關注 GC Time長短及間隔
-
C划乖、查看是否old Gen贬养,Eden是否存在持續(xù)上升
-
5、添加插件Tracer琴庵,Tracer可以監(jiān)控Heap误算、PerGen、Cleass迷殿、Treads等等
總結:
通過JMC錄制JFR飛行記錄和通過VisualVM監(jiān)控實時的虛擬機信息儿礼,進行調整優(yōu)化。
針對性的去調整JVM內存庆寺、新生代蚊夫、年代的空間大小、數(shù)據(jù)庫連接池大小止邮、MySQL最大連接數(shù)等这橙。
不斷的分析和調整奏窑,直到找到合適的JVM參數(shù)配置,找到最合適的參數(shù)屈扎,將這些參數(shù)應用到所有服務器埃唯,并進行后續(xù)跟蹤。
參考:
https://www.cnblogs.com/xifengxiaoma/p/9402263.html
https://my.oschina.net/yygh/blog/650507