JVM調優分析演練:
Jconsole中對內存為如下結構:

原始代碼:
public static void main(String[] args) { BigInteger [] pArr=new BigInteger [10000]; pArr[0]=new BigInteger("0"); pArr[1]=new BigInteger("1"); for (int i = 2; i < 10000; i++) { pArr[i]=pArr[i-1].add(pArr[i-2]); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("第"+i+":"+pArr[i]); }
步驟:
- 啟動程序生成斐波那契 並保存到數組中
- 啟動java分析工具 jconsole
問題1.連接失敗:

啟動之后 鏈接本地JAVA進程失敗:在運行的JAVA中加入如下參數:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8011 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
如下圖:

進程實際情況如下,使用情況:


通過觀察發現一次次的堆內存使用量有較大幅度的變化,多次進行GC。
進一步分析堆內存情況。

每次經過GC之后老年區一直都在提升,說明對象在進行GC后被移動到老年區了。

Eden新生區,對象隨着時間的變化生成的速度越來越快,GC不斷進行回收操作,系統頻繁調用GC。

存活期對象,在不斷的進行GC操作之后,將被不斷的從eden區copy到survive區,通過經過不多gc回收標記,在14:57時被批量移動到old區,所以空間在不斷下降。

而非堆區數據一致保持較平穩狀況,所以內存較為平穩。


通過分析發現,堆區對象在不斷生成,並且不斷增加,即使在進行回收的時候也無法回收掉,可以理解為,此處有與不斷產生 斐波那契 序列並存儲出現的問題,由於后續的數據非常大,所以非必須應該放棄緩存,或在獲得結果后進行轉存,如數據庫等。
另外,我們可以查看線程情況,通過下圖可以查看main方法中的Thread.sleep();方法話費了2638,可以在程序中去掉。

下圖為程序運行的整體情況:

下面對代碼進行修改:
BigInteger temp1=new BigInteger("0"); BigInteger temp2=new BigInteger("1"); BigInteger temp3=new BigInteger("0"); for (int i = 2; i < 10000; i++) { temp3= temp2; temp2=temp1.add(temp2); temp1=temp3; try { Thread.sleep(5); } catch (Exception e) { // TODO: handle exception } System.out.println("第"+i+":"+temp2); }
舍棄存儲之后結果如下:老年區,不到3M與第一個8M,變成了原來的37.5%效果明顯。

系統垃圾收集部明顯。


