責怪糟糕的代碼(或不良代碼對象)并不能幫助您發現瓶頸,提高 Java™ 應用程序速度,猜測也不能幫您解決。Ted Neward 引導您關注 Java 性能監控工具,從5 個技巧開始,使用Java 5 的內置分析器JConsole 收集和分析性能數據。
當應用程序性能受到損害時,大多數開發人員都驚慌失措,這在情理之中。跟蹤 Java 應用程序瓶頸來源一直以來都是很麻煩的,因為 Java 虛擬機有黑盒效應,而且 Java 平臺分析工具一貫就有缺陷。
然而,隨著 Java 5 中 JConsole 的引入,一切都發生了改變。JConsole 是一個內置 Java
性能分析器,可以從命令行或在 GUI shell
中運行。它不是完美的,但是當尖頭老板來問你關于性能的問題時,用它來應對還是綽綽有余的——這比查詢 Papa Google 要好得多。
在本期 5 件事 系列中,我將向您展示 5 個方法,使您可以輕松地使用 JConsole(或者,它更高端的 “近親” VisualVM )來監控 Java 應用程序性能和跟蹤 Java 中的代碼。
1. JDK 附帶分析器
許多開發人員沒有意識到從 Java 5 開始 JDK 中包含了一個分析器。JConsole(或者 Java
平臺最新版本,VisualVM)是一個內置分析器,它同 Java 編譯器一樣容易啟動。如果是從命令行啟動,使 JDK 在 PATH 上,運行
jconsole 即可。如果從 GUI shell 啟動,找到 JDK 安裝路徑,打開 bin 文件夾,雙擊 jconsole。
當分析工具彈出時(取決于正在運行的 Java 版本以及正在運行的 Java 程序數量),可能會出現一個對話框,要求輸入一個進程的 URL 來連接,也可能列出許多不同的本地 Java 進程(有時包含 JConsole 進程本身)來連接。
使用 JConsole 進行工作
在 Java 5 中,Java 進程并不是被設置為默認分析的,而是通過一個命令行參數 —
-Dcom.sun.management.jmxremote — 在啟動時告訴 Java 5 VM 打開連接,以便分析器可以找到它們;當進程被
JConsole 撿起時,您只能雙擊它開始分析。
分析器有自己的開銷,因此最好的辦法就是花點時間來弄清是什么開銷。發現 JConsole
開銷最簡單的辦法是,首先獨自運行一個應用程序,然后在分析器下運行,并測量差異。(應用程序不能太大或者太小;我最喜歡使用 JDK 附帶的
SwingSet2 樣本。)因此,我使用 -verbose:gc 嘗試運行 SwingSet2 來查看垃圾收集清理,然后運行同一個應用程序并將
JConsole 分析器連接到它。當 JConsole 連接好了之后,一個穩定的 GC 清理流出現,否則不會出現。這就是分析器的性能開銷。
2. 遠程連接進程
因為 Web 應用程序分析工具假設通過一個套接字進行連通性分析,您只需要進行少許配置來設置 JConsole(或者是基于 JVMTI 的分析器,就這點而言),監控/分析遠程運行的應用程序。
如果 Tomcat 運行在一個名為 “webserve” 的機器上,且 JVM 已經啟動了 JMX 并監聽端口 9004,從
JConsole(或者任何 JMX 客戶端)連接它需要一個 JMX URL
“service:jmx:rmi:///jndi/rmi://webserver:9004/jmxrmi”。
基本上,要分析一個運行在遠程數據中心的應用程序服務器,您所需要的僅僅是一個 JMX URL。更多關于使用 JMX 和 JConsole 遠程監控和管理的信息,參見 參考資料。)
3. 跟蹤統計
JConsole 有許多對收集統計數據有用的選項卡,包括:
Memory:在 JVM 垃圾收集器中針對各個堆跟蹤活動。
Threads:在目標 JVM 中檢查當前線程活動。
Classes:觀察 VM 已加載類的總數。
這些選項卡(和相關的圖表)都是由每個 Java 5 及更高版本 VM 在 JMX 服務器上注冊的 JMX 對象提供的,是內置到 JVM
的。一個給定 JVM 中可用 bean 的完整清單在 MBeans
選項卡上列出,包括一些元數據和一個有限的用戶界面來查看數據或執行操作。(然而,注冊通知是在 JConsole 用戶界面之外。)
使用統計數據
假設一個 Tomcat 進程死于 OutOfMemoryError。如果您想要弄清楚發生了什么,打開 JConsole,單擊
Classes 選項卡,過一段時間查看一次類計數。如果數量穩定上升,您可以假設應用程序服務器或者您的代碼某個地方有一個 ClassLoader
漏洞,不久之后將耗盡 PermGen 空間。如果需要更進一步的確認問題,請看 Memory 選項卡。
4. 為離線分析創建一個堆轉儲
生產環境中一切都在快速地進行著,您可能沒有時間花費在您的應用程序分析器上,相反地,您可以為 Java 環境中的每個事件照一個快照保存下來過后再看。在 JConsole 中您也可以這樣做,在 VisualVM 中甚至會做得更好。
先找到 MBeans 選項卡,在其中打開 com.sun.management 節點,接著是 HotSpotDiagnostic
節點。現在,選擇 Operations,注意右邊面板中的 “dumpHeap” 按鈕。如果您在第一個(“字符串”)輸入框中向 dumpHeap
傳遞一個文件名來轉儲,它將為整個 JVM 堆照一個快照,并將其轉儲到那個文件。
稍后,您可以使用各種不同的商業分析器來分析文件,或者使用 VisualVM 分析快照。(記住,VisualVM 是在 Java 6 中可用的,且是單獨下載的。)
5. JConsole 并不是高深莫測的
作為一個分析器實用工具,JConsole 是極好的,但是還有更好的工具。一些分析插件附帶分析器或者靈巧的用戶界面,默認情況下比 JConsole 跟蹤更多的數據。
JConsole 真正吸引人的是整個程序是用 “普通舊式 Java ” 編寫的,這意味著任何 Java
開發人員都可以編寫這樣一個實用工具。事實上,JDK 其中甚至包括如何通過創建一個插件來定制 JConsole 的示例(參見 參考資料)。建立在
NetBeans 頂部的 VisualVM 進一步延伸了插件概念。
如果 JConsole(或者
VisualVM,或者其他任何工具)不符合您的需求,或者不能跟蹤您想要跟蹤的,或者不能按照您的方式跟蹤,您可以編寫屬于自己的工具。如果您覺得
Java 代碼很麻煩,Groovy 或 JRuby 或很多其他 JVM 語言都可以幫助您更快完成。
您真正需要的是一個快速而粗糙(quick-and-dirty)的由 JVM 連接的命令行工具,可以以您想要的方式確切地跟蹤您感興趣的數據。
結束語
Java 性能監控不止于 JConsole 或 VisualVM — 在 JDK 中隱藏著一整套工具,只是大多數開發人員并不知道。 本系列
中的下一篇文章將深入探究一些實驗性的命令行工具,可以幫助您挖掘更多的您所需要的性能數據。因為這些工具通常只關注特殊數據,比一個完整的分析器更小更
輕巧,所以它們的性能開銷要小一些。