在Java SE 6 中監視和診斷性能問題

Java™ Platform, Standard Edition 6 (Java SE) 專注於提升性能,提供的增強工具可以管理和監視應用程序以及診斷常見的問題。本文將介紹Java SE 平臺中監視和管理的基本知識,並提供 Java SE 6 中相關增強的詳細信息。
Java SE 6 對性能進行了深入研究,使用增強的工具管理和監視應用程序並且診斷常見問題。這些改進包括:
  • 監視和管理 API 增強
  • 正式支持增強的圖形監視工具 JConsole
  • 提供增強的 Java 虛擬機(JVM)測試工具
本文介紹了 Java SE 平臺的監視和管理基本知識,並詳細介紹了最新版本中的性能監視和管理增強。還介紹了 Java SE 6 平臺提供的診斷和故障排除工具。
要從本文獲益,您應當非常熟悉較早 Java SE 版本中引入的監視和管理功能。更多背景信息,請參閱 參考資料。
監視和管理 API
Java SE 5 中引入的 java.lang.management 包定義了 9 個 MBean,稱爲平臺 MBeanMXBean(請參閱 參考資料)。每個 MXBean 封裝了 JVM 的一個單獨的功能區。從 Java SE 5 開始,JVM 包含了一個內置的 MBean 服務器,稱爲平臺 MBean 服務器。MBeans 位於其中並由其管理。表 1 列出了 Java 平臺中的 9 個 MXBeans:

表 1. 平臺 MBean
管理接口 託管的資源
ClassLoadingMXBean 類裝載器
CompilationMXBean 編譯器
MemoryMXBean 內存
ThreadMXBean 線程
RuntimeMXBean 運行時
OperatingSystemMXBean 操作系統
GarbageCollectorMXBean 垃圾收集器
MemoryManagerMXBean 內存管理器
MemoryPoolMXBean 內存池
任何應用程序都可獲得並使用 JVM 提供的平臺 MBean,方法是獲得目標 bean 的實例並調用合適的方法。MXBean 可用來監視本地和遠程 JVM 的行爲並獲得相關信息。
平臺 MBean 可提供對信息的訪問,例如裝載的類的數量、JVM 正常運行時間、內存消耗量、正在運行的線程的數量,以及線程競爭統計信息。
您可以使用以下兩種方式之一監視和管理 JVM 資源:
  • 直接訪問 MXBean 接口
  • 使用 MBeanServer 接口進行間接訪問
使用 MXBean 接口直接訪問
您可以從一個靜態工廠方法獲得一個 MXBean 實例,該方法可以使您直接訪問本地運行的 JVM 的 MXBean 接口。ManagementFactory 類提供靜態工廠方法獲得 MXBean。清單 1 演示瞭如何使用該工廠獲得 RuntimeMXBean 並獲得其中一個標準屬性 VmVendor 的值:

清單 1. 直接訪問 MXBean
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
// Get the standard attribute "VmVendor"
String vendor = mxbean.getVmVendor();

使用 MBeanServer 接口進行間接訪問
平臺 MBeanServer 接口使用 MXBeanServerConnection,使您能夠連接到遠程 JVM 並訪問運行在這些平臺上的 MXBean。您可以使用 ManagementFactory 類的 getPlatformMBeanServer 方法訪問平臺 MBean 服務器。清單 2 演示瞭如何獲得運行在遠程 JVM 上的 RuntimeMXBean 並獲得 VmVendor 屬性的值:

清單 2. 間接訪問 MXBean
MBeanServerConnection serverConn;
try {
   //connect to a remote VM using JMX RMI
   JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://<addr>");
   JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
   serverConn = jmxConnector.getMBeanServerConnection();
   ObjectName objName = new 
   ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
   // Get standard attribute "VmVendor"
   String vendor = 
   (String) serverConn.getAttribute(objName, "VmVendor");
} catch (...) { }

有關 MXBeans 和 java.lang.management API 的更詳細信息,請參閱 參考資料 。
Java SE 6 中的 API 增強
Java SE 5 引入了 java.util.concurrent.locks 包,它爲鎖定和等待條件提供了一種框架。這種框架有別於 Java 的內置同步支持並允許更加靈活地使用鎖。
Java SE 6 爲 java.lang.management 包的 java.util.concurrent.locks 添加了支持。這包括可提供鎖信息的新類以及對 ThreadInfoThreadMXBeanOperatingSystemMXBean 接口的增強。
Java SE 6 引入了兩個新類:
  • LockInfo 包含有關鎖的信息。
  • MonitorInfo 擴展了 LockInfo 幷包含有關對象監視鎖的信息。
ThreadInfo 類利用了這些新的對象以及引入的三種新方法:
  • getLockInfo() 返回 LockInfo 對象,給定線程將被阻塞以等待該對象。
  • getLockedMonitors() 返回當前被給定線程鎖定的 MonitorInfo 對象。
  • getLockedSynchronizers() 返回 LockInfo 對象,提供當前由給定線程鎖定的可擁有的同步程序。
在 Java SE 5 中,ThreadMXBean.getThreadInfo 方法只報告線程正在等待獲取的對象監視器或是被阻塞的監視器。Java SE 6 對這些方法進行了增強,從而可以報告線程正在等待獲取的 AbstractOwnableSynchronizer
4 個新的方法被添加到 ThreadMXBean 接口中:
  • isObjectMonitorUsageSupported() 將測試虛擬機是否支持對對象監視器的使用情況進行監視。
  • isSynchronizerUsageSupported() 測試虛擬機是否對可擁有的同步程序使用情況進行監視。
  • findDeadlockedThreads() 返回處於死鎖狀態的線程的 ID 數組。死鎖線程被阻塞,防止進入對象監視器或同步程序。
  • dumpAllThreads() 爲所有活動線程返回堆棧跟蹤和同步信息。
最後,OperatingSystemMXBean 接口將進行更新,以包括 getSystemLoadAverage() 方法,它可以返回前一分鐘的系統負載平均值。
除了提供編程支持以外,Java SE 6 還包括了一些診斷和故障排除工具,可用來檢測問題並監視 JVM 資源使用情況。接下來兩節將介紹並演示其中幾個可用的診斷工具。





Java 監視和管理控制檯(JConsole)
Java SE 6 提供了對 JConsole 的正式支持,這是 Java 5 SE 中引入的監視和管理控制檯。JConsole 使您能夠在運行時監視各種 JVM 資源統計信息。這種特性特別適用於檢測死鎖、鎖競爭、內存泄漏和循環線程。它可以連接到一個本地或遠程 JVM 並可用來進行監視:
  • 線程狀態(包括相關的鎖)
  • 內存使用情況
  • 垃圾收集
  • 運行時信息
  • JVM 信息
以下小節將介紹 Java SE 6 對 JConsole 做出的增強。有關如何啓動和使用 JConsole 的更多信息,請參閱 參考資料。
Attach API 支持
從 Java SE 6 開始,JConsole 實現了新的 Attach API。該 API 由兩個包組成 — com.sun.tools.attachcom.sun.tools.attach.spi — 可將應用程序的實現過程動態連接到目標虛擬機並在 JVM 內運行代理。
過去,對於要使用 JConsole 進行監視的應用程序,要求使用 -Dcom.sun.management.jmxremote 選項啓動;現在,應用程序不再需要使用這個選項啓動。對動態連接的支持使 JConsole 能夠監視任何支持 Attach API 的應用程序。JConsole 在啓動時將自動檢測兼容的應用程序。
增強的 UI 和 MBean 表示
Java SE 6 對 JConsole 進行了更新,使它具有類似於 Windows® 操作系統或 GNOME 桌面的感觀(取決於所運行的平臺)。後文中顯示的屏幕截圖使用的是 Windows XP 並展示了與之前版本不同的 UI 特性。
一旦啓動並與應用程序相關聯,將顯示由 6 個選項卡組成的 JConsole 視圖。每個選項卡表示一個不同的 JVM 資源或一組資源:
  • Overview
  • Memory
  • Threads
  • Classes
  • VM Summary
  • MBeans
Overview 選項卡以圖形的格式顯示有關內存使用、線程、類和 CPU 使用情況的信息。Overview 選項卡在一個頁面中顯示了一組相關信息,而在以前需要在多個選項卡之間進行切換才能顯示。圖 1 展示了一個示例應用程序的 Overview 選項卡:

圖 1. JConsole Overview 選項卡
JConsole
Overview 選項卡顯示了 4 個反映 VM 資源使用情況的圖形以及一個挑選列表,可以修改顯示結果的時間範圍。第一幅圖像 Heap Memory Usage 顯示堆內存量,隨時間流逝以 GB 的單位增加。該圖有助於檢測內存泄漏。如果您的應用程序出現了內存泄漏,堆內存使用量將隨時間穩步增長。
Threads 圖形隨時間的增長描繪活動線程的數量,而 Classes 圖形描繪所裝載的類的數量。CPU Usage 圖表描述應用程序在其生命週期的不同時間點的 CPU 使用百分比。
圖 2 顯示的 VM Summary 選項卡是對 Java SE 6 版本的另一個新的增強。它提供了有關 JVM 的詳細信息,包括總的運行時間、線程信息、裝載的類、內存統計信息、垃圾收集和操作系統信息。

圖 2. JConsole VM Summary 選項卡
JConsole
MBeans 選項卡進行了增強,可以更輕鬆地訪問 MBean 的操作和屬性。它顯示所有註冊到平臺中的 MBean 的信息,通過該選項卡可以訪問所有平臺 MBeans。左側的樹結構顯示當前運行的所有 MBean。當選擇一個 MBean 時,其 MBeanInfo 和描述符將顯示在右側的表中,如圖 3 所示:

圖 3. JConsole MBean 選項卡
JConsole
選擇 Attributes 節點將顯示 MBean 的所有屬性,如圖 4 所示的 Threading MBean:

圖 4. MBean 屬性
MBean
注意,方框右側的屬性及其值對應於通過前文介紹的 java.lang.management 包的 ThreadMXBean API 獲得的屬性值,通過雙擊屬性值可獲得所列屬性的其他信息,只有粗體顯示的屬性值可被展開。例如,雙擊 AllThreadIds 值將顯示 22 個線程的線程 ID,如圖 5 所示:

圖 5. 展開的屬性值
展開的屬性值
可寫的屬性以藍色顯示並可以通過單擊它們進行編輯並輸入新值。例如,圖 5 所示的 ThreadContentionMonitoringAvailable 屬性就可以以這種方式在 JConsole 視圖中進行編輯。
選擇左側樹結構中的 Operations 節點將顯示與該 MBean 有關的操作。MBean 操作以按鈕的形式顯示在右側的區域中,並且當單擊時將調用指定的方法。圖 6 顯示了可用於 ThreadMXBean 的操作:

圖 6. MBean 操作
MBean
HotSpot Diagnostic MBean
在 Java SE 6 中,JConsole 提供了對 HotSpot Diagnostic MBean 的支持。這個引入的 MBean 允許您執行 on-the-spot 診斷操作。其 API 允許用戶在運行時執行堆轉儲並設置其他 VM 選項。您可以從 MBean 選項卡訪問 HotSpot Diagnostic MBean,方法爲展開 com.sun.management 節點並選擇 HotSpotDiagnostic。圖 7 顯示了可用於 HotSpot Diagnostic MBean 的方法:

圖 7. HotSpot Diagnostic MBean
HotSpot
JConsole 插件支持
從 Java SE 6 開始,JConsole 提供了插件支持,允許您構建自己的插件來和 JConsole 一起運行。例如,您可以向 JConsole 主視圖添加一個自定義選項卡,用於訪問特定於應用程序的 MBeans 並執行自己的監視活動。
您必須擴展抽象的 com.sun.tools.jconsole.JConsolePlugin 類,創建一個自定義的 JConsole 插件。您將爲插件實現 2 個方法,使之正確顯示在 JConsole 視圖中:
  • newSwingWorker() 返回 SwingWorker 對象,它將對插件執行 GUI 更新。
  • getTabs() 返回被添加到 JConsole 窗口中的選項卡圖。
JConsole 使用其服務提供者機制檢測並裝載所有插件類。因此,您必須爲包含 META-INF/services/com.sun.tools.jconsole.JConsolePlugin 文件的 JAR 文件提供插件類。該文件應當包含一組完全符合規則的插件類名,其中每行顯示一個類名。要將新插件裝載到 JConsole 視圖,使用以下命令在命令行中運行 JConsole:
jconsole -pluginpath plugin_path

命令中的 plugin_path 指目錄路徑或者 JConsole 插件的歸檔。您可以指定多條路徑。
Java SE 6 附帶了一個示例 JConsole 插件,稱爲 JTop。JTop 將顯示當前應用程序內運行線程的 CPU 使用情況。要運行 JConsole 和 JTop,執行下面的命令:
jconsole -pluginpath JAVA_HOME/demo/management/JTop/JTop.jar

圖 8 展示了 JConsole 的一個實例,它選擇了 JTop 選項卡。左列顯示了所有運行線程的名稱。對於每個線程,將顯示它的 CPU 使用情況和線程狀態。當統計信息發生變化時,視圖將自動刷新。JTop 插件可用於通過高 CPU 使用量識別線程。

圖 8. JConsole JTop 插件
JConsole





監視和故障排除工具
除 JConsole 外,Java SE 6 還提供了對其他命令行工具的支持。這些診斷工具可以連接到任何應用程序而不要求應用程序以特殊模式啓動。它們使您能夠獲得更多應用程序信息,從而確定它是否按預期運行。注意,列出的這些工具仍處於實驗性質,未來的 Java SE 版本未必能夠提供完全的支持。
監視工具
Java SE 6 包括了三個命令行工具,如表 2 所示,這些工具可用於監視 JVM 性能統計信息:

表 2. 監視工具
工具 說明
jps JVM 進程狀態工具
jstat JVM 統計信息監視工具
jstatd JVM jstat 守護程序
jps 工具爲目標系統的當前用戶列出虛擬機。這對於使用 JNI Invocation API 而不是標準 Java 啓動程序啓動 VM 的環境特別有用。在這些環境中,通常很難從進程列表中識別 Java 進程。jps 工具解決了這個問題。
下面的例子演示了 jps 工具的使用。在命令行輸入 jps,該工具即可爲具有訪問權限的用戶列出虛擬機和進程 ID,如清單 3 的示例所示:

清單 3. 使用 jps 工具
$ jps
16217 MyApplication
16342 jps

jstat 工具使用 JVM 的內置測試工具,提供有關性能和所運行應用程序的資源消耗信息。該工具有助於診斷性能問題、與堆大小和垃圾收集有關的特殊問題。
jstatd 守護程序是一個 Remote Method Invocation (RMI) 服務器應用程序,它將監視 JVM 的創建和終止並提供接口以允許遠程監視工具連接到運行在本地主機的 JVM。例如,這個守護程序允許 jps 工具列出遠程系統中的進程。
有關這些工具的更多文檔和使用示例,請參閱 參考資料。
故障排除工具
Java SE 6 還提供了一些故障排除工具,如表 3 所示,這些工具可幫助您找出應用程序中運行異常的部分:

表 3. 故障排除工具
工具 說明
jinfo 配置信息
jhat 堆轉儲瀏覽器
jmap 內存映射
jsadebugd 服務能力代理調試程序
jstack 堆棧跟蹤
jinfo 命令行工具從運行中的 Java 進程或崩潰轉儲(crash dump)中獲取配置信息,並對系統屬性和用於啓動虛擬機的標記進行打印。
jhat 工具提供了一種方便的方法,可以在堆快照中瀏覽對象結構。Java SE 6 版本中引入的這個工具可以取代 Heap Analysis Tool (HAT),有助於檢測內存泄漏。
jmap 命令行工具爲運行中的 VM 或核心文件打印與內存有關的統計信息。該工具還可以使用 jsadebugd 守護程序查詢遠程機器中的進程或核心文件。jmap 工具可檢測出是否過度使用了完成器,後者可導致出現 OutOfMemoryError 錯誤。
Serviceability Agent Debug Daemon (jsadebugd) 連接到一個 Java 進程或一個核心文件,並充當一個調試服務器。該工具當前只能用於 Solaris OS 和 Linux®。諸如 jstackjmapjinfo 這樣的遠程客戶機可以通過 Java RMI 連接到這種服務器上。
jstack 命令行工具連接到指定的進程或核心文件,並打印所有連接到虛擬機的線程的堆棧跟蹤信息,包括 Java 線程和 VM 內部線程,有時也包括本地堆棧框架。該工具還執行死鎖檢測。它使用 jsadebugd 守護程序查詢遠程機器上的進程或核心文件。jstack 工具可用於檢測死鎖問題。
關於這些工具的更多文檔和使用示例,請參考 參考資料。





結束語
Java 6 平臺對 VM 測試、管理 API 和 JDK 工具提供了一些增強,可幫助有效地確定和診斷 Java 應用程序中的性能和內存問題。本文介紹了對 Java SE 監視和管理框架添加的增強以及爲開發人員提供的診斷命令行工具。
Java 應用程序的平均性能隨時間穩步提高。現在,使用 Java SE 6 版本,Java 性能可與 C 或 C++ 相媲美。在很多情況下,Java 代碼的運行速度顯著提升。您還可以使用本文介紹的工具實現更好的性能優化。請您親自嘗試。我們可以確保幫您找到以前從未進行過的應用程序優化。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章