java虛擬機跟蹤調試參數

1.1 跟蹤垃圾回收-讀懂虛擬機日誌

Java的一大特色就是支持自動的垃圾回收(GC),但是有時候,如果垃圾回收頻繁出現,或者佔用了太長的CPU時間,就不得不引起重視。此時,就需要一些跟蹤參數來進一步甄別垃圾回收器的效率和效果。

最簡單的一個GC參數是-XX:+PrintGC,使用這個參數啓動Java虛擬機後,只要遇到GC,就會打印日誌。

如果需要更加詳細的信息,則可以使用-XX:+PrintGCDetails參數。他的輸出可能如下:

GC 詳細輸出

從這個輸出可以看到,系統經歷了3次GC,第一次僅爲新生代GC,回收的效果是新生代從回收前的8MB左右降到了1M左右。整個堆從22MB左右降到了17MB。

第二次爲Full GC,它同時回收了新生代、老年代和永久區。從日誌顯示,新生代在這次GC中沒有釋放空間(嚴格來說,這是GC日誌的一個小bug,事實上,在這次Full GC完成後,新生代被清空,由於GC日誌輸出時機的關係,各個版本的JDK日誌多少有些不太精確的地方),老年代從16MB降到了13MB。整個堆大小從26MB左右降到了13MB左右(這個大小完全與老年代實際大小相等,因此可以推斷,新生代實際上已被清空)。永久區的大小沒有變化。日誌的最後,顯示了GC花費的時間,其中user表示用戶態CPU耗時,sys表示系統CPU耗時,real表示GC實際經歷的時間。

如果需要更全面的堆信息,還可以使用參數-XX:+PrintHeapAtGC。他會在每次GC前後分別打印堆的信息。

如果需要分析GC發生的時間,還可以使用-XX:+PrintGCTimeStamps參數,該參數會在每次GC發生時,額外輸出GC發生的時間,該輸出時機爲虛擬機啓動後的時間偏移量。

默認情況下,GC的日誌會在控制檯輸出,這不便於後續分析和定位問題。爲此,虛擬機允許將GC日誌以文件的形式輸出,可以使用參數-Xloggc指定。

1.2 類加載/卸載的跟蹤

一般情況下,系統加載的類存在於文件系統中,以jar的形式打包或者以class文件的形式存在,可以直接通過文件系統查看。但是隨着動態代理、AOP等技術的普遍使用,系統也ji'ke'neng極可能在運行時動態生成某些類,這些類相對比較隱蔽,無法通過文件系統找到。

可以使用參數-verbose:class跟蹤類的加載和卸載,也可以單獨使用參數-XX:+TraceClassLoading跟蹤類的加載,使用參數-XX:+TraceClassUnloading跟蹤類的卸載。

Java虛擬機還允許研發人員在運行時打印、查看系統中類的分佈情況,只要在系統啓動時加上-XX:+PrintClassHistogram參數,然後在Java控制檯按下Ctrl+Break組合鍵,控制檯就會顯示當前的類信息柱狀圖。

1.3 系統參數查看

參數-XX:+PrintVMOptions可以在程序運行時,打印虛擬機接收到的命令行顯式參數。

參數-XX:+PrintCommandLineFlags可以打印傳遞給虛擬機的顯式和隱式參數。

二、學習堆的配置參數

2.1 最大堆和初始堆的設置

  • Xms:初始堆
  • Xmx:最大堆

在實際工作中,也可以直接將初始堆-Xms和最大堆-Xmx設置相等,這樣好處是可以減少程序運行時進行的垃圾回收次數,從而提高程序的性能。

2.2 新生代的配置

參數-Xmn可以用於設置新生代的大小。設置一個較大的新生代會減小老年代的大小,這個參數對系統性能以及GC行爲有很大的影響,新生代的大小一般設置爲整個堆空間的1/3到1/4左右

參數-XX:SurvivorRatio用來設置新生代中eden空間和from/to空間的比例關係,他的含義如下:

-XX:SurvivorRatio=eden/from=eden/to

實際工作中,堆分佈的基本策略是:儘可能將對象預留在新生代,減少老年代GC的次數。

除了可以使用-Xmn指定新生代的絕對大小外,還可以使用參數-XX:NewRatio來設置新生代和老年大的比例,他的含義如下:

-XX:NewRatio=老年代/新生代

堆的分配參數示意圖

2.3 堆溢出處理

在Java程序的運行過程中,如果堆空間不足,則有可能拋出內存溢出錯誤(OutOfMemory),簡稱OOM。一旦發生這類問題,系統就會被迫退出。如果發生在生產環節,可能會引起嚴重的業務中斷。爲了不斷改善系統,避免或減少這類錯誤的發生,需要在發生錯誤時,獲得儘可能多的現場信息。Java虛擬機提供了參數-XX:+HeapDumpOnOutOfMemoryError,使用該參數,可以再內存溢出時導出整個堆信息。和他配合使用的還有-XX:HeapDumpPath,可以指定導出堆的存放路徑。

三、非堆內存的參數配置

3.1 方法區配置

方法區主要存放類的元信息。

在JDK1.6和JDK 1.7等版本中,可以使用-XX:PermSize和-XX:MaxPermSize配置永久區大小。其中-XX:PermSize表示初始的永久區大小,-XX:MaxPermSize表示最大永久區。

在JDK 1.8中,永久區被徹底移除,使用了新的元數據區存放類的元數據。默認情況下,元數據區只受系統可用內存的限制,但依然可以使用參數-XX:MaxMetaspaceSize指定元數據區的最大可用值。

3.2 棧配置

通過-Xss指定線程的棧大小。

3.3 直接內存配置

最大可以直接內存可以使用參數-XX:MaxDirectMemorySize設置,如不設置,默認值爲最大dui堆空間,即-Xmx。當直接內存使用量達到-XX:MaxDirectMemorySize時,就會觸發垃圾回收,如果垃圾回收不能有效釋放足夠空間,直接內存溢出依然會引起系統的OOM。

四、虛擬機的工作模式

目前Java虛擬機支持Client和Server兩種運行模式。默認情況下,虛擬機會根據當前計算機系統環境自動選擇運行模式。使用-version參數可以查看當前的模式,如下:

java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)

與Client模式相比,Server模式啓動較慢,因爲Server模式會嘗試收集更多的系統性能信息,使用更復雜的優化算法對程序進行優化。因此,當系統完全啓動並進入運行穩定期後,Server模式的執行速度會遠遠快於Client模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章