每個Java程式設計師必須知道的5個JVM命令列標誌
本文是Neward & Associates的總裁Ted Neward為developerworks獨家撰稿“你不知道5個……”系列中的一篇,JVM是多數開發人員視為理所當然的Java功能和效能背後的重負荷機器。然而,我們很少有人能理解JVM是如何進行工作的—像任務分配和垃圾收集、轉動執行緒、開啟和關閉檔案、中斷和/或JIT編譯Java位元組碼,等等。
不熟悉JVM將不僅會影響應用程式效能,而且當JVM出問題時,嘗試修復也會很困難。
本文將介紹一些命令列標誌,您可以使用它們來診斷和調優您的Java虛擬機器效能。
1.DisableExplicitGC
我已記不清有多少次使用者要求我就應用程式效能問題提供諮詢了,其實只要跨程式碼快速執行grep,就會發現清單1所示的問題—原始Java效能反模式:
清單 1. System.gc();
// We just released a bunch of objects, so tell the stupid // garbage collector to collect them already! System.gc();
顯式垃圾收集是一個非常糟糕的主意——就像將您和一個瘋狂的鬥牛犬鎖在一個電話亭裡。儘管呼叫的語法是依賴實現的,但如果您的JVM正在執行一個分代的垃圾回收器(大多數是)System.gc();強迫VM執行一個堆的“全部清掃”,雖然有的沒有必要。全部清掃比一個常規GC操作要昂貴好幾個數量級,這只是個簡單數學問題。
您可以不把我的話放在心上—Sun的工程師為這個特殊的人工錯誤提供一個JVM標誌;-XX:+DisableExplicitGC標誌自動將System.gc()呼叫轉換成一個空操作,為您提供執行程式碼的機會,您自己看看System.gc()對於整個JVM執行有害還是有利。
2.HeapDumpOnOutOfMemoryError
您有沒有經歷過這樣的情況:JVM不能使用,不斷丟擲OutOfMemoryError,而您又不能為自己建立偵錯程式來捕獲它或檢視出現了什麼問題?像這類偶發和/或不確定的問題,通常使開發人員發瘋。
買者自負
並不是任何VM都支援所有命令列標誌,Sun/Oracle的VM除外。查明一個標誌是否被支援的最好方法是試用它,看它是否正常工作。倘若這些標誌在技術上是不支援的,那麼,使用它們您要承擔全部責任。如果這些標誌中的任何一個使您的程式碼、您的資料、您的伺服器或您的一切消失得無影無蹤,我、Sun/Oracle和IBM都將不負責任。為以防萬一,建議先在虛擬(非常生產)環境中實驗。
在這個時刻您想要的是,在JVM消亡之際捕獲堆的一個快照——正好-XX:+HeapDumpOnOutOfMemoryError命令可以完成這一操作。
執行該命令通知JVM拍攝一個“堆轉儲快照”,並將其儲存在一個檔案中以便處理,通常使用jhat實用工具(我在上一篇文章中介紹過)。您可以使用相應的-XX:HeapDumpPath標誌指定到儲存檔案的實際路徑。(不管檔案儲存在哪,務必確保檔案系統和/或Java流程必須要有許可權配置,可以在其中寫入。)
3.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/amods引數將新Integer放在預設的引數前面。
4.verbose
對於虛擬的或任何型別的Java應用程式,-verbose是一個很有用的一級診斷使用程式。該標誌有三個子標誌:gc、class和jni。
開發人員嘗試尋找是否 JVM 垃圾收集器發生故障或者導致效能低下,通常首先要做的就是執行 gc。不幸的是,解釋 gc 輸出很麻煩 — 足夠寫一本書。更糟糕的是,在命令列中列印的輸出在不同的 Java 版本中或者不在不同的 JVM 中會發生改變,這使得正確解釋變得更難。
一般來說,如果垃圾收集器是一個分代收集器(多數“企業級”VMs都是)。某種虛擬標誌將會出現,來指出一個全部清掃GC通路;在Sun JVM中,標誌在GC輸出行的開始以“[FullGC...]”形式出現。
想要診斷ClassLoader和/或不匹配的類衝突,class可以幫上大忙。它不僅報告類何時載入,還報告類從何處載入,包括到JAR的路徑(如果來自JAR)。
jni很少使用,除了使用JNI或本地庫時。開啟時,它將報告各種JNI事件,比如,本地庫何時載入,方法何時彈回;再一次強調,在不同JVM版本中,輸出會發生變化。
5.Command-line-X
我列出了JVM中提供的我喜歡的命令列選項,但是還有一些更多的需要您自己發現,執行命令列引數-X,列出JVM提供的所有非標準(但大部分都是安全的)引數—例如:
-Xint,在解釋模式下執行JVM(對於測試JIT編譯器實際上是否對您的程式碼起作用或者驗證是否JIT編譯器中有一個bug,這都很有用)。
-Xloggc:,和-verbose:gc做同樣的事,但是記錄一個檔案而不輸出到命令列視窗。
JVM命令列選項時常發生變化,因此,定期檢視是一個好主意。甚至,您深夜盯著監控器和下午5點回家和妻子孩子吃頓晚飯,(或者在Mass Effect 2中消滅您的敵人,根據您的喜好),它們都是不一樣的。
結束語
在生產環境中,命令列標誌不是為永久使用而設計的——事實上,除了您終止用來調優JVM垃圾收集器的標誌,沒有一個非標準命令列標記是專用於生產使用的。但是,作為工具來刺探在其他方面完全不透明的虛擬機器的內部工作,是非常有用的。
相關文章
- Java程式設計師必須掌握的5個註解!Java程式設計師
- 每個Java程式設計師都必須知道的四種負載均衡演算法Java程式設計師負載演算法
- Java程式設計師必須掌握的7個Java效能指標!Java程式設計師指標
- 每個程式設計師1小時內必須解決的5個程式設計問題程式設計師
- 每個程式設計師都必須遵守的程式設計原則程式設計師
- Java程式設計師必須瞭解的7個效能指標,你都知道嗎?Java程式設計師指標
- 列舉幾個Java程式設計師通用的、必須掌握的框架Java程式設計師框架
- PHP程式設計師必須知道的兩種日誌PHP程式設計師
- 程式設計師必須知道的幾個國外IT網站程式設計師網站
- 每個Java程式設計師必備的8個開發工具Java程式設計師
- 每個優秀程式設計師必須具備的技術技能程式設計師
- 作為一個Java程式設計師,這 8 個開源類庫你必須知道!Java程式設計師
- 網頁設計師必須知道的6個小技巧網頁
- Java 程式設計師必須掌握的 Linux 命令Java程式設計師Linux
- 每個程式設計師應該知道的12個API程式設計師API
- 程式設計師必須知道的幾個Git程式碼託管平臺程式設計師Git
- 每個 Python 程式設計師都要知道的日誌實踐Python程式設計師
- 前端設計師必須知道的10個重要的CSS技巧前端CSS
- 設計師升職加薪必須知道的10個設計網站網站
- 每個程式設計師必知之SEO程式設計師
- 關於 Unicode 每個程式設計師應該知道的 5 件事Unicode程式設計師
- 每個程式設計師應該知道12件事程式設計師
- 15個IT程式設計師必須思考的問題程式設計師
- 29 個你必須知道的 Linux 命令Linux
- Java程式設計師須知的七個日誌管理工具Java程式設計師
- 每個程式設計師和設計師必做的10項運動程式設計師
- 每個程式設計師都必讀的10篇文章程式設計師
- 程式設計師必須掌握的五個seo知識程式設計師
- 有理想的程式設計師必須知道的15件事程式設計師
- 每個程式設計師都應該知道的 15 個最佳 PHP 庫程式設計師PHP
- AppStore 中5個必須知道的基本設定APP
- 每個程式設計師必須掌握的常用英語詞彙分享給你(建議收藏)程式設計師
- iOS程式設計師必須知道的Android要點iOS程式設計師Android
- 每個 Android 開發者必須知道的資源集錦Android
- 每個Android程式設計師應該知道的KotlinAndroid程式設計師Kotlin
- 每個程式設計師都該知道的編碼準則程式設計師
- Web開發者和設計師必須要知道的 iOS 8 十個變化WebiOS
- 必須知道的28個HTML5特性、技巧HTML