Java虛擬機深刻理解系列所有文章更新中...html
前面在學習JVM的知識的時候,通常都須要利用相關參數進行分析,而分析通常都須要用到一些分析的工具,由於通常使用IDEA,而VisualVM對於IDEA也不錯,因此就選擇VisualVM來分析JVM性能,這篇文章就介紹一下如何利用VisualVM進行性能分析,以及在分析以前須要知道一些GC優化的原則,GC優化的目的,以及遇到問題時怎麼去解決問題的方法。java
開發大型 Java 應用程序的過程當中不免遇到內存泄露、性能瓶頸等問題,好比文件、網絡、數據庫的鏈接未釋放,未優化的算法等。隨着應用程序的持續運行,可能會形成整個系統運行效率降低,嚴重的則會形成系統崩潰。爲了找出程序中隱藏的這些問題,在項目開發後期每每會使用性能分析工具來對應用程序的性能進行分析和優化。算法
VisualVM 是一款免費的性能分析工具。它經過 jvmstat、JMX、SA(Serviceability Agent)以及 Attach API 等多種方式從程序運行時得到實時數據,從而進行動態的性能分析。同時,它能自動選擇更快更輕量級的技術儘可能減小性能分析對應用程序形成的影響,提升性能分析的精度。數據庫
這裏有兩種方式:服務器
若是沒有按照IDEA插件的話,咱們須要找到JDK的按照目錄bin下找到以下執行程序。微信
而後雙擊執行,就會出現界面,以下;markdown
可是,咱們通常使用IDEA,因此會使用插件,就是下面這種方式。網絡
先在插件中找到VisualVM安裝;併發
安裝了以後,在運行的地方就會多出現兩個VisualVM的運行按鈕;
jvm
這樣運行程序以後,就能夠自動打開VisualVM程序了。
這一部分先對這個工具作一個簡要的介紹,看看基本有哪些咱們會用到的功能。
在沒有添加其餘插件的時候,是隻有下面幾個功能的。
如上圖所示,概述基本上都是咱們的系統屬性、運行程序時設置的JVM參數等信息的展現,因此,這一部分可讓咱們查看這些信息。
監視這個界面的功能仍是頗有做用的,能夠看到cup運行狀況、堆的使用狀況、類的狀況以及線程的動態狀況。
所以,咱們能夠利用這個界面查看cpu狀況好很差,更重要的是,咱們能夠查看堆的使用狀況,這對於咱們分析JVM仍是很是重要的。
如上圖因此,能夠看到全部的線程的狀況,是運行、休眠、等待、駐留、監視等狀況。
注意, 以上這些都不是關鍵,關鍵是VisualVM中還有一個很重要的功能,能夠添加插件獲取更多的功能。
正是由於有了插件的擴展功能,因此這個工具才如此強大,VisualVM能夠作到如下:
在工具->找到可用插件,安裝便可。
下一部分咱們就利用已經安裝的插件Visual GC
進行分析。
Visual GC
分析虛擬機內存區域這部分會用到一些Java虛擬機的一些基礎知識,因此,查看這部分以前,請先查看這篇文章:。
在這個界面分爲如下幾個部分。
那麼知道這些參數以後,怎麼去分析虛擬機到底運行是好是壞呢,這個時候,咱們須要瞭解一些Java虛擬機基礎的優化知識。
首先,須要瞭解一些GC優化的原則。
另外,咱們須要知道咱們GC優化的目的。
通常,咱們須要執行的有如下幾點;
至於怎麼算合適,後面我會經過一個實例講解。
其實,若是想要知道更多JVM內存分配和回收策略的原理,能夠查看這篇文章:JVM內存分配和回收策略的原理。
通常咱們執行了咱們的程序以後,接下來就是須要查看GC的狀態了,接着分析結果,判斷是否須要進行優化。
通常若是達到如下的指標,就不須要進行GC了。
Minor GC
執行時間不到50ms
,Minor GC
執行不頻繁,約10
秒一次;Full GC
執行時間不到1s
,Full GC
執行頻率不算頻繁,不低於10
分鐘1次;咱們先看一個GC狀態須要優化的例子,在這個實例中,咱們給堆分配的最大最小的值都是64M
(很小的堆大小)。
/** * VM Args:-Xms64m -Xmx64m -XX:+HeapDumpOnOutOfMemoryError * @author 歐陽思海 */ public class HeapTest { static class StaticObject { } public static void main(String[] args) { List<StaticObject> list = new ArrayList<StaticObject>(); int i = 1; //不斷的向堆中添加對象 while (true) { list.add(new StaticObject()); i++; System.out.println(i); System.out.println(list.size()); } } }
因爲分配的堆內存過小,因此致使,堆溢出。
接着咱們查看一下Visual GC
的監視狀況。
咱們能夠從堆的使用狀況看出,基本已經使用完。
從上圖可知,在短短的運行時間中,Eden進行了49次GC,雖然時間短,可是能說明一個問題,新生代堆內存分配的空間過小,致使頻繁GC。
同時,Old老年代也進行了33次GC,雖然運行時間也在不須要優化的範圍內,並且從Survivor能夠看出,基本沒有GC,說明這些都是大對象,直接進入到了Old老年代,致使GC頻繁。
因此,咱們須要進行的優化就是加大新生代和老年代堆內存的大小,同時減小大對象的產生。
咱們將VM參數改成:-Xms512m -Xmx512m -Xmn128m -XX:+HeapDumpOnOutOfMemoryError
,運行大概5分鐘再次查看結果。
首先沒有出現堆內存溢出。
加大了堆內存,因此堆內存沒有出現問題。
加大了堆內存以後,Eden新生代進行了66次GC,使用時間3.381s基本知足要求(執行時間不到50ms,Minor GC執行不頻繁,約10秒一次),同時老年代old進行了2次GC,使用時間4.127s,這裏仍是有待優化的,不太知足優化要求。
點擊堆 dump這個按鈕就會生成 dump文件,咱們能夠分析類及對象的一些狀況。
分析以後發現,StaticObject對象大多,沒有進行GC,問題主要在這裏,因此,下一步須要解決這個問題。
經過以上分析能夠說明一個問題,加大了堆內存以後,新生代和老年代的GC狀況大大的改善了,可是還有大對象的問題,因此還有待優化。
修改程序,以下:
/** * VM Args:-Xms512m -Xmx512m -Xmn128m -XX:+HeapDumpOnOutOfMemoryError * * @author 歐陽思海 */ public class HeapTest { /* static class StaticObject { }*/ public static void main(String[] args) { int i = 1; while (true) { i++; System.out.println(i); } } }
堆一直運行良好。
此次相對於上次相比,老年代的狀況已經改善了,沒有GC,說明大對象不存在了。
經過上面的分析跟優化,就知足GC的需求了,不須要再優化了。
經過上面的分析及使用,VisualVM基本的使用以及如何利用VisualVM進行Java虛擬機優化相信你已經掌握了,若是還想了解更過關於Java虛擬機的知識及優化文章,請看本系列的其餘文章。
一、原創不易,老鐵,文章須要你的 點贊 讓更多的人看到,但願可以幫助到你們!
二、文章有不當之處,歡迎指正,若是喜歡微信閱讀,你也能夠關注個人微信公衆號:
好好學java
,公衆號已有 6W 粉絲,回覆:1024,獲取公衆號的大禮包,公衆號長期發佈 Java 優質系列文章,關注咱們必定會讓你收穫不少!