『壹』 64位計算中的java虛擬機(JVM)性能測試
隨著DEC(Digital Equipment Corp)公司Alpha處理器在 年末的發布 就意味著這個世界開始進入 位計算的時代 緊接著 全球幾大主要計算機公司 如IBM Hewlett Packard(惠普) Fujitsu(富士通) Sun Microsystems 也發布了各自相應的產品進入到 位 這個市場 在 年 Fujitsu旗下的HAL Computer發布了業界第一台基於 位SPARC CPU的工作站 SPARC 此後不久 Sun發布了大眾期盼已久的Ultra Ultra 工作站 其內置了Sun的 位UltraSPARC處理器 時間轉換到 年 IBM發布了其第一個 位PowerPC RISC晶元 RS 在 年 IBM對RS 進行改良 使其支持SMP 這就是Power 如今看起來 對 位計算來說 其整整花了五年的時間 才在 年開始大量進入市場 在本文中 將主要涉及兩個現在廣泛應用的 位平台 AMD 與PowerPC 並分別使用IBM與Sun Microsystems這兩個Java語言巨頭提供的Java虛擬機(JVM) 通過SPECjvm 與SPECjbb 的測試 來評價 位與 位中JVM的性能 (注 SPECjvm 與SPECjbb 來自Standard Performance Evaluation Corp )AMD 是Advanced Micro Devices(AMD)公司的 位平台 其擴展了工業標準的x 指令集架構 並設計在不降低任何性能的前提下 於 位模式中完全兼容現有的x 應用程序與操作系統 在 年 月 AMD發布了Opteron 遵循AMD 架構的第一款處理器 與其同時 年 IBM發布了PowerPC 其是源自IBM Power 雙核CPU的單核處理器 從此 IBM把 位PowerPC架構帶到了桌面系統與低端伺服器領域 另外要說明一點 PowerPC 也像Power 一樣 可在不降低性能的前提下 本地執行 位指令 不久之後 在 年 月 由Apple Computer公司設計 基於PowerPC CPU的Power Mac G 電腦上市 Java背景介紹 在第一款 位處理器誕生不久 Java技術也出世了 並由此改寫歷史 Java是一種健壯的 通用的 面向對象的 構架中立的 可移植的 安全的 多線程的編程語言 並帶有隱式內存管理功能 Java面向對象的特性在很大程度上與C++相似 但加入了更多的介面與擴展以創建更具靈活性的解決方案 與C++不同的是 Java不支持操作符重載 多重繼承和自動類型強制 Java通過廣泛的運行時檢查和內置的例外處理機制 達到健壯性的目的 編譯器所生成的只是位元組碼指令 其是獨立於任何特定平台的 這樣就保證了架構中立性 可移植性是通過指定基本數據類型大小和其算術操作符的行為來達到的 例如 int總表示一個有符號的 位整數 而float總表示一個 位的IEEE 浮點數 Java同時也有一系列的同步原語 其基於廣泛使用的條件變數範式 自動內存垃圾回收(GC)簡化了Java編程的難度 並極大地降低了bug的數目 但也使運行機制稍微復雜了點 在 年 也就是DEC公司發布第一款 位處理器的前一年 Sun Microsystems開始了一個名為 the Green Project 的計劃 目的是要搶占 下一波計算 的先機 並為此提前做好准備 計劃得出的最初結論是 移動數字設備與計算機的融合將會很快出現 在 年的夏天 計劃小組演示了* (星 ) 一個通過動畫式觸摸屏控制的交互性手持娛樂設備 通過使用Oak 一種全新的編程語言 這個設備可控制很多不同的平台 而由James Gosling開發的Oak 其最主要的特點在於它是一個徹底獨立於處理器的語言 在往後的幾年中 這種語言被用於Internet 之後成為大眾所知的Java 而 Oak 這個名字則因為版權問題從此消失了 在 年 月 Sun正式宣布Java的誕生 這是一種程序員只需編寫一次 但卻可在多種操作系統及多種硬體平台上運行的語言 編寫一次 隨處運行 在 年 Sun發布了Java開發工具包(JDK ) 其後不久 個主要的操作系統開發商宣布支持Java技術 當中也包括Microsoft 其以每年大約 萬美元取得五年時間的Java許可協議 在 年 月 Sun發布了Java平台的第一個即時(JIT)編譯器 在 年 月 JDK 面世 在隨後的三周時間里 達到了 萬次的下載量 到了 年初 這個數字達到兩百萬 在 年末 Java 平台發布了 大概半年後 也就是 年年中 Sun發布了三個版本的Java平台 J ME(Java Micro Edition) 應用於移動 無線及有限資源的環境 J SE(Java Standard Edition) 應用於桌面環境 J EE(Java Enterprise Edition) 應用於基於Java的應用伺服器 此後 廣泛應用的Java技術出現了一些framework 如Enterprise JavaBeans (EJB)和JavaServer Pages (JSP) Java技術的隨後一次升級 是出現在 年 月的J SE 幾周後 其獲得了Apple公司Mac OS X的工業標準的支持 J SE 發布於 年 月份 對Java平台來說 這是一個幾乎全新的產品 與J SE 相比 其多了近 %的類和介面 在這些新特性當中 還提供了廣泛的XML支持 安全套接字支持(通過SSL與TLS協議) 全新的I/O API 正則表達式 日誌與斷言 在 年 月 是Java最近的一次發布 J SE (內部版本號 ) 代號 Tiger 現已提供公開下載 Tiger包含了從 年發布 版本以來的最重大的更新 其中包括泛型支持 基本類型的自動裝箱 改進的循環 枚舉類型 格式化I/O及可變參數 Java虛擬機(JVM)是一個軟體規范 相關軟體有責任遵守它 以運行編譯為Java位元組碼的程序 JVM是一個抽象的計算機制 並獨立於操作系統 具有編譯後的程序體積小 可防止執行惡意代碼等特點 其沒有預先假設基於任何特定的實現技術 不管是硬體還是操作系統 通常我們有幾個常用的JVM軟體 其 位與 位版本性能有所不同 但它們都包括JIT編譯器和垃圾回收功能(GC) JIT編譯器從JDK 開始就是JVM的一部分了 當時Java只是用於瀏覽器客戶端動態效果顯示的一種技術 JIT編譯器實現了程序執行之前Java位元組碼到硬體機器碼的動態翻譯 其背後的思想在於 相比Java源代碼 位元組碼更小也更容易編譯 但付出的代價是需要在Java位元組碼編譯為機器碼時花上一點時間 但與直接把Java源代碼編譯為機器碼相比 時間還是少得多的 在 位與 位的JVM中 相應的JIT在把Java位元組碼編譯為最終的機器碼時 所花的時間稍微有所不同 但還能進行一些優化 另外 在IBM與Sun這兩個版本的客戶端與服務端程序上 總體性能也會有所不同 垃圾回收是一種自動內存管理系統 它會收回對象不再需要使用的內存 從軟體工程的角度來看 垃圾回收最大的一個好處就是 程序員不用再操心那些低級的內存管理細節了 同時 垃圾回收也去除了源代碼中兩個最大的bug 內存未釋放(內存泄漏)與過早釋放(指針崩潰) 內存回收在Java程序運行期間佔了一個很重要的部分 因為它必須被經常執行以釋放對象不再訪問的Java堆 由於在 位與 位平台上 Java堆中的數據大小會有所變化 所以會因為 位與 位JVM的性能差異 導致相應垃圾回收的性能也會有所不同
位背景介紹 位計算有幾個重要組成部分 第一就是 位定址 實際上 位定址是通過 位整數寄存器達到的(或RISC中所指的通用寄存器) 位寄存器允許 位的指針裝入到單個的寄存器中 而 位的指針 才是可以定址訪問更大內存的實質所在 當 位處理器只能訪問到 位元組或 GB內存時 位處理器理論上卻可定址訪問 位元組或 × GB內存 在現代的 位系統中 可定址的內存的實際限制通常比理論值低一點 具體依賴於特定的硬體架構和操作系統 舉例來說 在基於Linux的操作系統中 受限於當前Linux內核數據結構的設計 可定址的內存最多為 位元組或 GB 位計算的第二個重要方面 就是 位整數運算 要提醒的是 這可不是簡單地因為有了可存儲更多更大整數量 更寬的 位整數寄存器而帶來的必然結果 其最直接的影響就是對那些需要處理密集大數值整數運算的程序而言 可帶來性能上的飛躍 第三個方面 即 位計算的特性 是 位操作系統與程序的應用 相關的軟體必須全面支持硬體的 位特性 包括 位定址和運算 通常還有一些附帶的好處 如 可操作更多更大的文件 管理更大的磁碟等等 位計算所帶來的影響 目前已在許多程序中得到了體現 資料庫伺服器現在可定址更大的內存 以維持更大的緩沖池 數據緩存 或在內存中進行排序以減少相關的I/O操作 也能給每個用戶分配更多的內存 支持更多的用戶 或對更大的數據文件進行操作 模擬或其他計算密集的程序也將從中受益 如 現在可以在內存中分配更大的數組了 最後 別忘了還有大量的Java程序 J EE應用伺服器 現在也能充分享受到 位計算所帶來的好處了 位計算的主要缺點是 與它們 位的兄弟相比 位二進制文件一般都更大 因此 最終生成的機器碼體積也更大 在系統緩存與旁路轉換緩存(TLB)大小不變的情況下 可能會同時降低兩者的命中率 這就是說 在一定程度上性能會有所損失 性能評測 此處用於測試 位與 位JVM性能的系統 是兩台 位雙CPU工作站 一台是基於AMD 技術的Opteron系統 而另一台是基於PowerPC 的Apple Power Mac G 兩台工作站都分別運行基於Linux的 位操作系統 受測試的JVM分別來自於IBM和Sun 將使用SPEC的SPECjvm 和SPECjbb 來測試相應JVM的性能 其中SPECjvm 使用了以下項目測試客戶端性能 ·_ _press 一個流行的壓縮程序 ·_ _jess 一個Java版的NASA CLIPS基於規則的專家系統 ·_ _db 數據管理基準測試軟體 ·_ _javac JDK Java編譯器 ·_ _mpegaudio 一個MPEG 音頻解碼器 ·_ _mtrt 一個對圖像文件進行處理的雙線程程序 ·_ _jack 一個分析程序生成器 SPECjbb (Java商業基準程序)是一個用於服務端的基準測試程序 其模仿了三層體系結構 是一個通用類型的Java服務端應用程序 通過運行SPECjvm 以秒為單位記錄了每個基準測試的運行時長 時間越短越好 所有SPECjvm 測試的堆大小因JVM而有所變化 從最小值 MB至最大值 MB 在SPECjbb 測試中 記錄了在三種不同堆大小時的每秒執行操作數 更高的值代表更高的性能 每一個測試程序都運行三次 取成績最好的一次作為最後的結果 圖 與圖 顯示了在AMD 平台上 Linux版本的Sun Java Standard Edition Development Kit (J SE )在SPECjvm 和SPECjbb 中 位與 位的性能測試結果 在SPECjvm 測試中 只有三項 _ _press _ _mpegaudio _ _jack 在 位版本的JVM上比 位表現出更佳的性能 在SPECjbb 中 位版本的性能只在有足夠堆大小的情況下 才表現出更高的性能 其中在堆大小為 MB時 因為某些活動數據在 位JVM版本中體積更大 導致垃圾回收動作更頻繁 從而降低了程序性能
圖 圖 圖 與圖 顯示了在AMD 平台上 Linux版本的IBM Developer Kit for Linux Java Technology Edition Version GA在SPECjvm 和SPECjbb 中 位與 位的性能測試結果 其中 基準測試程序中有三項 _ _db _ _javac _ _jack 在 位環境下表現出了更佳的性能 另外 在SPECjbb 測試中 當面對三個不同大小的測試堆時 位IBM版本的JVM都沒有表現出比 位版本更好的性能 圖 圖 圖 與圖 顯示了在PowerPC 平台上 IBM Developer Kit for Linux Java Technology Edition Version GA在SPECjvm 和SPECjbb 中 位與 位的性能測試結果 此處 在所有SPECjvm 和SPECjbb 的測試中 位JVM的性能都不及 位平台 圖 圖 結論 基於運行Linux操作系統的PowerPC 平台的測試結果 表明如果在此平台上使用IBM的JVM 那麼 那些不需要 位特性的程序 還是讓它們運行在 位JVM中吧 因為在此平台的所有測試結果中 位JVM的性能都比 位平台低 而基於運行Linux操作系統的AMD 平台的測試結果 表明不管是Sun還是IBM的JVM 位與 位的性能都在伯仲之間 要注意的是 性能的差異是依賴於具體的應用程序與JVM的 如果需要最佳性能 就必須在某個特定的執行環境中測試某個特定的程序 以評價轉換到 位所帶來的潛在性能提升 有幾件事情需重點注意 第一 盡管SPECjvm 與SPECjbb 都是工業標準的基準測試程序 但它們的測試范圍有限 因此 就測試結果而言 只對一部分的Java程序正確 而不是所有 第二 隨著 位計算越來越被人們接受 我們期待 位程序會有所改進 包括 位JVM 也許其在將來會大幅提高性能 第三 此處只組合測試了幾種特定的硬體平台 操作系統與JVM 因此 如果要進一步地說明問題 恐怕只有在 位Windows XP/ 及 位Mac OS X上的進行JVM基準測試了 lishixin/Article/program/Java/hx/201311/26587
『貳』 什麼是Java虛擬機
虛擬機是一種抽象化的計算機,通過在實際的計算機上模擬模擬各種計算機功能來實現的。
Java虛擬機有自己完善的硬體架構,如處理器、堆棧、寄存器等,還具有相應的指令系統。JVM屏蔽了與具體操作系統平台相關的信息,使得Java程序只需生成在Java虛擬機上運行的目標代碼(位元組碼),就可以在多種平台上不加修改地運行。
這種解釋應該算是正確的,但是只描述了虛擬機的外部行為和功能,並沒有針對內部原理做出說明。搜段薯一般情況下我們不需要知道虛擬機的運行原理,只要專注寫java代碼就可以了,這也正是虛擬機之所以存在的原因--屏蔽底層操作系統平台的不同並且減少基於原生語言開發的復雜性,使java這門語言能夠跨各種平台(只要虛擬機廠商在特定平台上實現了虛擬機),並且簡單易用。這些都是虛擬機的外部特性,但是從這些信息來解釋虛擬機,未免太籠統了,無法讓我們知道內部原理。
從進程的角度解釋JVM
讓我們嘗試從操作系統的層面來理解虛擬機。我們知道,虛擬機是運行在操作系統之中的,那麼什麼東西才能在操作系統中運行呢?當然是進程,因為進程是操作系統中的執行單位。可以這樣理解,當它在運行的時候,它就是一個操作系統中的進程實例,當它沒有在運行時(作為可執行文件存放於文件系統中),可以把它叫做程序。
對命令行比較熟悉的同學,都知道其實一個命令對應一個可執行的二進制文件,當敲下這個命令並且回車後,就會創建一個進程,載入對應的可執行文件到進程的地址空間中,並且執行其中的指令。下面對比C語言和Java語言的HelloWorld程序來說明問題。
首先編寫C語言版的HelloWorld程序。
總結
寫到這里,基本上關於我對java虛擬機的理解就寫完了。這篇文章的主題雖然是深入理解Java虛擬機,但是你可能感覺一點也不「深入」,也只是泛泛而談。我也有這樣的感覺。限於自己水平有限,也只能這樣了,要是想深入理解java虛擬機,強烈建議讀一下三本書:
《深入Java虛擬機》
《深入理解Java虛擬機JVM高級特性與最佳實踐》
《Java虛擬機規范》
其實我也讀過這幾本書,但是它們對虛擬機的解釋也是基於一個外部模型,而沒有深入剖析虛擬機內部的實現原理。虛擬機是一個大而復雜的東西,實現虛擬機的人都是大牛級別的,如果不是參與過虛擬機的實現,應該很少有人能把它參透。本專欄後面的一些文章也參考了這三本書, 雖然講解Java語法的書不計其數, 但是深入講解虛擬機的書, 目前為止我就見過這三本,並且網上的資料也不是很多。
最後做一個總結:
1 虛擬機並不神秘,在操作系統的角度看來,它只是一個普通進程。
2 這個叫做虛擬機的進程比較特殊,它能夠載入我們編寫的class文件。如果把JVM比作一個人,那麼class文件就是我們吃的食物。
3 載入class文件的是一個叫做類載入器的子系統。就好比我們的嘴巴,把食物吃到肚子里。
4 虛擬機中的執行引擎用來執行class文件中的位元組碼指令。就好比我們的腸胃,對吃進去的食物進行消化。
5 虛擬機在執行過程中,要分配內存創建對象。當這些對象過時無用了,必須要自動清理這些無用的對象。清理對象回收內存的任務由垃圾收集器負責。就好比人吃進去的食物,在消化之後,必須把廢物排出體外,騰出空間可以在下次餓的時候吃飯並消化食物。
(2)java虛擬機性能擴展閱讀:
關於JAVA虛擬機的參數說明如下:
1、運行class文件
執行帶main方法的class文件,Java虛擬機[3]命令參數行為:
java <CLASS文件名>
注意:CLASS文件名不要帶文件後綴.class
例如:
java Test
如果執行的class文件是帶包的,即在類文件中使用了:
package <;包名>
那應該在包的基路徑下執行,Java虛擬機命令行參數:
java <;包名>.CLASS文件名
例如:
PackageTest.java中,其包名為:com.ee2ee.test,對應的語句為:
package com.ee2ee.test;
PackageTest.java及編譯後的class文件PackageTest.class的存放目錄如下:
classes
|__com
|__ee2ee
|__test
|__PackageTest.java
|__PackageTest.class
要運行PackageTest.class,應在classes目錄下執行:
java com.ee2ee.test.PackageTest
2、運行jar文件中的class
原理和運行class文件一樣,只需加上參數-cp <jar文件名>;即可。
例如:執行test.jar中的類com.ee2ee.test.PackageTest,命令行如下:
java -cp test.jar com.ee2ee.test.PackageTest
3、顯示JDK版本信息
當一台機器上有多個jdk版本時,需要知道當前使用的是那個版本的jdk,使用參數-version即可知道其版本,命令行為:
java -version
4、增加虛擬機可以使用的最大內存
Java虛擬機可使用的最大內存是有限制的,預設值通常為64MB或128MB。
如果一個應用程序為了提高性能而把數據載入內存中而佔用較大的內存,比如超過了默認的最大值128MB,需要加大java虛擬機可使用的最大內存,否則會出現Out of Memory的異常。啟動java時,需要使用如下兩個參數:
-Xms java虛擬機初始化時使用的內存大小
-Xmx java虛擬機可以使用的最大內存
以上兩個命令行參數中設置的size,可以帶單位,例如:256m表示256MB
舉例說明:
java -Xms128m -Xmx256m ...
表示Java虛擬機初始化時使用的內存為128MB,可使用的最大內存為256MB。
對於tomcat,可以修改其腳本catalina. sh(Unix平台)或catalina.bat(Windows平台),設置變數JAVA_OPTS即可,例如:
JAVA_OPTS='-Xms128m -Xmx256m'