Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> 你所不知道的五件事情--JVM的命令行選項

你所不知道的五件事情--JVM的命令行選項

編輯:Android開發實例

這是Ted Neward在IBM developerWorks5 things系列文章中的一篇,講述了關於JVM命令行參數的一些應用竅門,值得大家學習。(2010.09.01最後更新)

摘要:Java虛擬機有數百個命令行選項,只有經驗十分豐富的Java開發員才會使用這些選項去調優Java運行時環境。學習如何監控並記錄編譯器性能,禁用顯示的垃圾收集(System.gc()),擴展JRE,及其它。

    JVM是Java應用程序功能與性能背後的實際工作者,大部分Java開發者認為這是理所當然的。然而我們中很少有人真正地理解JVM是如何做到這些事的--如,分配並收集垃圾對象,擺弄線程,打開及關閉文件,解釋和/或使用JIT編譯Java字節碼,以及其它任務。
    不熟悉JVM不僅會使你在應用程序的性能方面付出代價,而且當JVM出了某些問題時,還很難進行修復。
    5 things系列的這篇文章介紹一些好用的命令行JVM選項,你可以使用它們去診斷並調優Java虛擬機的性能。

1. DisableExplicitGC
    我無法告訴你我已經多少次被要求就應用程序性能問題進行咨詢了,而我只是簡單地對代碼文件執行grep命令就能發現如清單1所示的程序--這就是早期Java性能的反模式:

Listing 1. System.gc();

// We just released a bunch of objects, so tell the stupid
// garbage collector to collect them already!
System.gc();


顯式地執行垃圾收集器確實是個壞主意--這就像把你自己與一個瘋狂的斗牛犬鎖在電話亭中那樣。雖然該調用的確切語義依賴於具體的實現,但假設你的JVM運行著一個分代垃圾收集器(大多數JVM也正是如此),System.gc()方法強制要求VM對Heap進行"全面清掃",即便有些並不是必要的。一般地,全面清掃的開銷要比常規GC操作要大幾個數量級,而常規GC操作的開銷只會產生純數學的負作用。
     但不要相信我的話--為了這個特殊的人為錯誤,Sun的工程師們為我們提供了一個JVM選項:-XX:+DisableExplicitGC選項自動地將System.gc()調用置為無用操作,給你一個機會去執行程序,並讓你自己看看System.gc()是否已經幫助或損害整個JVM的執行。

2. HeapDumpOnOutOfMemoryError
    你肯定曾經遇到過JVM不斷死掉的情況,即拋出OutOfMemoryError,在你的一生中似乎都不能設置一個調試器去捕獲這個錯誤,並看看是出了什麼問題?像這些不時發生且/或無法確定的問題能使一個開發員完全瘋掉。
    你所想的,就是在在JVM快死掉時能夠捕獲Heap的快照--這正是命令-XX:+HeapDumpOnOutOfMemoryError所要做的。
    運行該命令就是告訴JVM創建一個"Heap轉儲快照",並將它保存為一個文件以便於處理,常常使用jhat工具(在前一篇文章中我有介紹過)。使用相應的命令-XX:HeapDumpPath,就指定被保存文件的確切路徑。(不論文件保存在何處,要先確保文件系統和/或Java進程有必要的僅限配置能在那兒寫文件。)

3. bootclasspath
    偶爾地,將某個類,該類不同於原有的或以某種方式擴展而得到的JRE所存儲的類,置於類路徑中是有用的。(一個例子就是新的Java Crypto API適配器)。如果你想擴展JRE,那麼你的定制實現需要能用於引導ClassLoader,該ClassLoader會加載java.lang.Object以及它在rt.jar中的所有同族成員。
    盡管你可以打開rt.jar並將你定制實現或新的包放入其中,但在技術上這就違反了當初你在下載JDK時所同意的協議。
    相反地,應該使用JVM自己的-Xbootclasspath選項,以及它的兄弟選項-Xbootclasspath/p和-Xbootclasspath/a。
    -Xbootclasspath允許你設置整個引導類路徑,該路徑一般地必須包含一個針對rt.jar的引用,再加上一批隨JDK發布但不是rt.jar一部分的其它JAR文件。-Xbootclasspath/p會向已有引導類路徑中預置值,然後-Xbootclasspath/a會將它連接起來。
    例如,如果你已經修改了原有的java.lang.Integer,並將修改後的程序放入子目錄,mods,然後參數-Xbootclasspath/a mods將會在加載原有默認Integer類之前加載這個新的Integer實現。

4. verbose
    對於任何類型的Java應用,-verbose都是頭等有用的診斷工具。該選項有三個子選項:gc,class和jni。
    一般地,如果JVM垃圾收集器在運行並導致了低下的性能,那麼gc就是開發員們第一次想要弄清楚的地方。不幸地是,解釋gc的輸出需要些技巧,這足夠成為一整本書的主題了。更糟地是,在命令行窗口打印出的輸出對於不同的Java發行版是不同的,或者對於不同的JVM也是不同的,這造成難以對其進行正確地解釋。
    一般來說,如果垃圾收集器是分代收集器(大多數"企業級"VM正是如此),會有一些布爾型選項去指定是否使用完全清除;在Sun的JVM中,這樣的選項會以[Full GC ...]的形式出現在GC輸出行的開頭。
    class會是一個生命保護者,它嘗試著診斷ClassLoader和/或不匹配的類沖突。它不僅會報告類是在何時被加載的,而且也會報告類是從何處被加載的,包括JAR文件的路徑,如果這個類來自於一個JAR的話。
    jni很少用到,除非你有使用JNI和原生庫。當啟用該選項時,它會報告各種JNI事件,例如原生庫何時被加載的,以及方法何時被綁定的;另外,該報告輸出會由於不同的Java版或JVM實現而不盡相同。

5. 命令行-X
    我已經列出了一些JVM提供的且我比較喜歡的命令行選項,但還有更多的選項你自己就能發現到。運行命令行參數-X列出所有JVM支持的非標准的(但多數就是安全的)參數--就像這些:
    -Xint,使JVM以解釋模式進行運行(對於測試JIT編譯器是否真的作用到你的程序,或是證明你是否有Bug在JIT編譯器中,該選項是很用的)。
    -Xloggc:,該參數所做的與-verbose:gc相同,但它會把日志記錄到一個文件中,而不是一股腦地輸出在命令窗口中。
    JVM命令行選項改了一次又一次,所以隔一段時間再去看會是一個好主意。這種區別就好像是,花上一整夜金城湯池盯著你的顯示器,或者是下午五點就回家與愛人和孩子享用美餐(或是在Mass Effect 2中屠殺敵人,這取決於你的偏好)。

結論
    命令行選項的本意不是為了在產品環境中永久使用--事實上,除了你(可能)最終用於調優JVM垃圾收集器的選項之外,非標准的命令選項都不會被刻意地用到產品中。但作為能夠窺探到完全不透明的虛擬機的內部工部情形的工具,它們是無價的。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved