JVM 是多數開發人員視為理所當然的 Java 功能和性能背後的重負荷機器然而我們很少有人能理解 JVM 是如何進行工作的 — 像任務分配和垃圾收集轉動線程打開和關閉文件中斷和/或 JIT 編譯 Java 字節碼等等不熟悉 JVM 將不僅會影響應用程序性能而且當 JVM 出問題時嘗試修復也會很困難本文將介紹一些命令行標志您可以使用它們來診斷和調優您的 Java 虛擬機性能
DisableExplicitGC
我已記不清有多少次用戶要求我就應用程序性能問題提供咨詢了其實只要跨代碼快速運行 grep就會發現清單 所示的問題 — 原始 java 性能反模式
清單 Systemgc();
顯式垃圾收集是一個非常糟糕的主意 — 就像將您和一個瘋狂的斗牛犬鎖在一個電話亭裡盡管調用的語法是依賴實現的但如果您的 JVM 正在運行一個分代的垃圾回收器(大多數是)Systemgc(); 強迫 VM 執行一個堆的 全部清掃雖然有的沒有必要全部清掃比一個常規 GC 操作要昂貴好幾個數量級這只是個簡單數學問題
您可以不把我的話放在心上 — Sun 的工程師為這個特殊的人工錯誤提供一個 JVM 標志; XX:+DisableExplicitGC 標志自動將 Systemgc() 調用轉換成一個空操作為您提供運行代碼的機會您自己看看 Systemgc() 對於整個 JVM 執行有害還是有利
HeapDumpOnOutOfMemoryError
您有沒有經歷過這樣的情況JVM 不能使用不斷拋出 OutOfMemoryError而您又不能為自己創建調試器來捕獲它或查看出現了什麼問題?像這類偶發和/或不確定的問題通常使開發人員發瘋
買者自負並不是任何 VM 都支持所有命令行標志Sun/Oracle 的 VM 除外查明一個標志是否被支持的最好方法是試用它看它是否正常工作倘若這些標志在技術上是不支持的那麼使用它們您要承擔全部責任如果這些標志中的任何一個使您的代碼您的數據您的服務器或您的一切消失得無影無蹤我Sun/Oracle 和 IBM? 都將不負責任為以防萬一建議先在虛擬(非常生產)環境中實驗
在這個時刻您想要的是在 JVM 消亡之際捕獲堆的一個快照 — 正好 XX:+HeapDumpOnOutOfMemoryError 命令可以完成這一操作
運行該命令通知 JVM 拍攝一個 堆轉儲快照並將其保存在一個文件中以便處理通常使用 jhat 實用工具您可以使用相應的 XX:HeapDumpPath 標志指定到保存文件的實際路徑(不管文件保存在哪務必確保文件系統和/或 Java 流程必須要有權限配置可以在其中寫入)
bootclasspath
定期將一個類放入類路徑是很有幫助的
這類路徑與庫存 JRE 附帶的類路徑或者以某種方式擴展的 JRE 類路徑略有不同
(新 Java Crypto API 提供商就是一個例子)
如果您想要擴展 JRE
那麼您定制的實現必須可以使用引導程序 ClassLoader
該引導程序可以加載 rt
jar 中的 java
lang
Object 及其所有相關文件
盡管您可以 非法打開 rt
jar 並將您的定制實現或新數據包移入其中
但從技術上您就違反了您下載 JDK 時同意的協議了
相反
使用 JVM 自己的
Xbootclasspath 選項
以及皮膚
Xbootclasspath/p 和
Xbootclasspath/a
Xbootclasspath 使您可以設置完整的引導類路徑(這通常包括一個對 rt
jar 的引用)
以及一些其他 JDK 附帶的(不是 rt
jar 的一部分)JAR 文件
Xbootclasspath/p 將值前置到現有 bootclasspath 中
並將
Xbootclasspath/a 附加到其中
例如
如果您修改了庫中的 java
lang
Integer
並將修改放在一個子路徑 mods 下
那麼
Xbootclasspath/a mods 參數將新 Integer 放在默認的參數前面
verbose
對於虛擬的或任何類型的 Java 應用程序
verbose 是一個很有用的一級診斷使用程序
該標志有三個子標志
gc
class 和 jni
開發人員嘗試尋找是否 JVM 垃圾收集器發生故障或者導致性能低下
通常首先要做的就是執行 gc
不幸的是
解釋 gc 輸出很麻煩 — 足夠寫一本書
更糟糕的是
在命令行中打印的輸出在不同的 Java 版本中或者不在不同的 JVM 中會發生改變
這使得正確解釋變得更難
一般來說
如果垃圾收集器是一個分代收集器(多數
企業級
VMs 都是)
某種虛擬標志將會出現
來指出一個全部清掃 GC 通路;在 Sun JVM 中
標志在 GC 輸出行的開始以
[Full GC
]
形式出現
想要診斷 ClassLoader 和/或不匹配的類沖突
class 可以幫上大忙
它不僅報告類何時加載
還報告類從何處加載
包括到 JAR 的路徑(如果來自 JAR)
jni 很少使用
除了使用 JNI 或本地庫時
打開時
它將報告各種 JNI 事件
比如
本地庫何時加載
方法何時彈回;再一次強調
在不同 JVM 版本中
輸出會發生變化
Commandline X
我列出了 JVM 中提供的我喜歡的命令行選項
但是還有一些更多的需要您自己發現
運行命令行參數
X
列出 JVM 提供的所有非標准(但大部分都是安全的)參數 — 例如
Xint
在解釋模式下運行 JVM(對於測試 JIT 編譯器實際上是否對您的代碼起作用或者驗證是否 JIT 編譯器中有一個 bug
這都很有用)
Xloggc:
和
verbose:gc 做同樣的事
但是記錄一個文件而不輸出到命令行窗口
JVM 命令行選項時常發生變化
因此
定期查看是一個好主意
甚至
您深夜盯著監控器和下午
點回家和妻子孩子吃頓晚飯
(或者在 Mass Effect
中消滅您的敵人
根據您的喜好)
它們都是不一樣的
結束語
在生產環境中
命令行標志不是為永久使用而設計的 — 事實上
除了您終止用來調優 JVM 垃圾收集器的標志
沒有一個非標准命令行標記是專用於生產使用的
但是
作為工具來刺探在其他方面完全不透明的虛擬機的內部工作
是非常有用的
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25594.html