JVM 統計信息
JVM 提供許多統計信息。這些統計信息涉及諸如即時 (JIT) 編譯、類加載、內存分配以及最有趣的垃圾收集之類基本的 JVM 特性。
即時編譯
JVM 可將字節代碼即時編譯為機器代碼。該動作類似于像您用于腳本語言的解釋器(如 Perl)所執行的動作。但是它更先進,提供許多優化措施,使得已解釋的字節代碼幾乎與預編譯的代碼運行得一樣快(有時更快)。顯然,執行 JIT 編譯需要開銷。度量應用程序需要多大開銷的兩個有用的統計信息是 JIT 編譯次數和執行這些編譯花費的時間總量。(有關 JIT 編譯的更多詳細信息,請參閱 參考資料。)
類加載
JVM 負責從應用程序的類使用的庫向應用程序和類中加載類。因此,這些類可能是從已部署在 Geronimo 中的 WAR 或 EAR 中加載的類,也可能是包含在 WAR 或 EAR 中的 JAR 文件,或者是由 Geronimo 容器加載的 JAR 中的類。如果類不用于延長的時間,則 JVM 還可以選擇卸載這些類。這將導致幾項重要的統計信息:加載的類的數量、卸載的類的數量、加載和卸載類花費的時間。
內存(堆)分配
在 Java 技術中沒有 malloc()
函數,這是因為 JVM 可自動為對象分配內存。對象從堆中分配;因此,使用的和空閑的堆內存數量是兩個非常重要的統計信息。監視堆分配是檢測可怕的內存泄漏最簡單的方法之一。
垃圾收集
這可能是 JVM 最有趣的統計信息。正像 JVM 為對象分配內存一樣,它還回收不再使用的對象上的內存。關于垃圾收集如何工作,包括您可以指示 JVM 用于其垃圾收集器的不同算法,有很多有趣的讀物。
還有許多關于垃圾收集器本身的有趣的統計信息。首先是調用垃圾收集器的頻率和垃圾收集過程中花費的時間。垃圾收集的開銷很大,因為本質上它會中止應用程序的執行以便可以檢驗對象。顯然,大量的垃圾收集可以真正減慢應用程序的運行速度。
其他有趣的統計信息與對象分代有關。垃圾收集器按代對對象進行分類,每代都指示對象已經經歷了一定次數的垃圾收集。(經歷很多次垃圾收集的對象比未經歷或者經歷了很少次數垃圾收集的對象被垃圾收集的可能性更小。)這樣的對象分類允許垃圾收集器檢驗更少的對象,使每次垃圾收集速度更快。因此,每代中對象的數量可能相當有趣,提供更好的方法來查找內存泄漏和很好的方法來考察潛在優化(如對象緩存和對象池)的影響。
![]() ![]() |
![]()
|
訪問 JVM 統計信息
有幾個可用的 JVM 實現,但最常見的是 Sun 的 HotSpot JVM(有關技術鏈接,請參閱 參考資料)。從 Java 2 Platform, Standard Edition (J2SE) 1.4.2 開始,HotSpot 進行了全面配備,提供許多上面描述的有用的統計信息。有好幾個方法用于獲得和分析這一數據。獲得 JVM 生成的統計信息之后,您可以訪問 Geronimo 的 JVM 并分析您的應用程序。
訪問方法
獲得一些 JVM 統計信息的最簡單的方法是通過命令行。HotSpot 識別許多命令行選項,其中幾個選項允許您定制堆大小和垃圾收集選項。也可以使用 -verbose:gc
選項。這可使 JVM 打印出以下形式的行:
[GC 70333K->65666K(98896K), 0.0007817 secs]
[Full GC 65666K->59333K(98896K), 0.0205250 secs]
上面示例中的第一行指示發生了一次垃圾收集。收集之前堆上使用了 70,333KB,收集之后使用了 65,666KB。第一行還指示總共有 98,896KB 的可用空間。最后,指出垃圾收集花費的時間,也即應用程序中止的時間量。第二行指示相同的信息,但表示一個完整的垃圾收集。完整的垃圾收集涉及 JVM 對堆上所有的對象進行檢驗,包括經歷了許多代、在部分垃圾收集上不會被分析的對象。
有關更詳細的信息,請使用 -XX:+PrintGCDetails
和 -XX:+PrintGCTimeStamps
選項。這些選項提供關于堆上對象的不同代的詳細信息。
對于看上去更為有趣的統計信息,可以使用專門的工具。開放源碼的工具和商業工具都可以使用。還可以使用 Sun 提供的一些用于與 HotSpot 一起使用的工具。jvmstat
項目包含幾個用于監視 JVM 統計信息的工具,包括一個叫做 Visual Garbage Collector 或 visualgc
的圖形工具, 它使用起來相對簡單。您需要 Java 5 或更高版本來運行 jvmstat
,盡管它可以附加和監視 1.4.2 或更高版本的 JVM。只需下載和解壓即可(有關下載鏈接,請參閱 參考資料)。將它添加到您的路徑,即可準備運行。啟動了 Java 進程時,請使用 jps
工具來通過鍵入 jps
標識其 JVM。它向您提供一個正在運行的 Java 進程的列表,這些進程以其 JVM 作為 ID。然后使用您想監視的進程的 ID 調用 visualgc
。jvmstat
發行版包括一個用于調用 visualgc
的 shell 腳本。如果安裝了 cygwin
這樣的工具,就可以在 *nix 或 Microsoft® Windows® 上調用 visualgc
了。此外,也可以按以下方式調用它:
java -Xbootclasspath/p:%JAVA_HOME%\lib\tools.jar -jar %JVMSTAT_HOME%\jars\visualgc.jar 316
其中 JAVA_HOME
環境變量指定安裝 JDK 的位置,而 JVMSTAT_HOME
指示安裝 jvmstat
包的位置。該行末尾的 316 是您想監視的 JVM 的 ID。該 jvmstat
包還包括一個 jstat 工具。它提供在 visualgc
中看到的絕大部分相同信息,只不過將其作為文本輸出。這對收集統計信息而言至關重要,然后可以將這些統計信息拖入另一個程序,以對其進行深入分析、生成有關它的報告,等等。本文集中討論使用 visualgc
對這些統計信息進行可視化。
清單 1 提供一個短程序,您可以運行來測試使用 jvmstat
進行監視。
|
這是一個簡單的程序。它使用了泛型,所以您需要 Java 5 。如果愿意,您可以容易地改變它以不使用泛型,然后它將用較舊的 JDK 運行。它通過創建可隨機調整大小的長整數數組導致內存分配。它通過隨機將這些數組的一部分(大約 20%)放入一個列表來模擬內存泄漏。因此,垃圾收集器可以回收在每個循環上分配的大多數內存,但它不能回收添加到列表中的數組。您可以試驗一些參數,比如睡眠大小和最大塊大小。它還可以接收命令行參數,所以您可以容易地告知它要執行多少次循環。
編譯 StatGen
之后,您可以簡單地從 java StatGen 100
開始。這執行 100 次循環。記住,您可以在命令行指定最小和最大堆大小。采用不同的最小和最大堆大小在運行 visualgc
時將產生截然不同的視覺效果。您還可以指定不同的垃圾收集算法;用 visualgc
監視 StatGen
時,將很好地理解這些算法的區別。
圖 1 展示了一些用 StatGen
運行 visualgc
的示例輸出。
圖 2 展示了最有趣的窗口。它首先展示了 JIT 編譯。在本例中,只有三個窗口,這對于這樣一個簡單的示例來說并不稀奇。它還展示了類加載器信息 —— 再說一遍,這很簡單,因為應用程序太簡單了。
接著,它展示了總體的垃圾收集統計信息。您會看到 123 次收集和進行垃圾收集所花費的總時間約為 0.3 秒。從第一個圖形中,您可以看到應用程序運行了大約 100 秒,所以進行垃圾收集花費了該時間的 0.3%。
還有關于不同分代的統計信息。Eden 空間顯示了從未通過垃圾收集的新對象。示例代碼生成許多這樣的新對象,并且它們很快就被收集掉。
注意兩個 Survivor 空間。它們基本上是較小的經歷過少數幾次垃圾收集的對象集。所有對象要么是立即準備收集的,要么是從未準備收集的,所以,如果它們到了 Survivor 空間,就將很快改變這種狀態。
接下來是較老的一代。這些對象經歷了大量垃圾收集。您可以看到穩定的對象增加,表明存在潛在的內存泄漏。最后,您看到的是 JVM 確定永遠不會被收集的對象的永久代。
直方圖窗口(參見 圖 3)展示了關于 Survivor 空間的數據 —— 此處列出的不多。
![]() ![]() |
![]()
|
Geronimo 和初始構建
在您前面下載的二進制和源安裝中有幾個目錄。二進制下載包括運行和使用 Geronimo 所必需的 Geronimo 的梗概。源下載包括所有 Geronimo 源代碼,包括用于構建整棵樹的 Maven 構建腳本。首先來看二進制發行版,然后再看源代碼發行版。
關于 Geronimo 示例應用程序的 JVM 統計信息
Geronimo 附帶了幾個示例 Web 應用程序。既然您有了一些從 JVM 提取 JVM 統計信息的工具,就可以容易地為 Geronimo 應用程序執行此操作。
啟動 Geronimo
僅僅啟動 Geronimo 并用 visualgc
監視它就相當有趣,如 圖 4、圖 5 和 圖 6 所示。
用標準的 java -jar %GERONIMO_HOME%/bin/server.jar
命令啟動 Geronimo。僅通過使用啟動命令上的 -server
選項即可獲得直接視圖,如 圖 7 所示。
注意,JIT 編譯少得多。這是因為在您使用 -server
選項啟動 JVM 時加載了更多的類。默認的啟動模式設計用于更快的啟動,以適應桌面應用程序。
在這兩種情況下,您都會在堆上看到許多長時間運行的對象,但是一旦 Geronimo 完全啟動,這個數量將趨于平緩。這展示所有正在被加載的服務器對象,如各種 GBeans 以及它們管理的服務。Geronimo 開發人員將因看不到內存泄漏的跡象而高興,因為老的一代和永久的一代分配趨于平緩。
示例 Web 應用程序
現在您也可以運行一些包含的 Geronimo Web 應用程序。圖 8 中的圖形展示 JSPX-XHTML 示例應用程序的垃圾收集動作。
您可以看到左側的對象突然增多,然后大部分對象將在呈現該頁面后消失,這與您所期望的一樣。您可以看到也對應于應用程序運行的 JIT 編譯和類加載事件。
既然了解了如何訪問和分析運行 Geronimo 的某個示例 Web 應用程序時生成的 JVM 統計信息,就可以開始分析自己的應用程序了。大概就是啟動 Geronimo、啟動 visualgc
,然后部署和/或啟動您的應用程序。對它運行一些事件,觀察它加載類、編譯字節代碼以及管理內存。
![]() ![]() |
![]()
|
結束語
JVM 統計信息在調優應用程序時非常寶貴。Sun 提供的工具讓您快速分析應用程序、執行優化并查看優化的效果。它們還允許試驗多個 JVM 選項,以對應用程序執行附加調整。Geronimo 的目標之一是提供高性能應用服務器,而 JVM 統計信息的分析是尋求最高應用程序性能的一項重要補充。
原文轉自:http://www.anti-gravitydesign.com