當然筆者的程度還很弱,不及許多已在Android或embedded system打滾多年的高手,但希望藉由以下的淺顯說明可以讓初階學習者了解JITcompiler 與 VM 的關係。
1. Java的效能比較差嗎?
很多人都把runtime的效能當作絕對比較指標,但是他們常常忽略到的是軟體開發的彈性與速度,在Java中透過標準API寫出一個類似MSN的聊天軟體(UI, data persistence, TCP/IP socket....etc)可能只需要N倍時間,但用C/C++可能需要3N甚至到10N以上的時間。
另外,現在能從SUN網站上download的JVM,都搭載了Just-In-Time compiler,這是一種動態Java method compiler,以Java method (A.doSomeThing())為單位,能夠動態的在程式執行時根據熱門程度編譯成機器碼(存至code cache)或只是直譯某個Java method,所以Sun也使用 "Hot Spot" VM作為產品名稱
所以,其實在JIT compiler的實作持續改進下,Java的程式執行效能已經近乎執行機器碼相同的速度。還以為Java執行效能比較差的人,其實已經落伍至少兩至三年以上
現在Sony PS3, HTC Magic/Hero裡,其實都有虛擬機器VM的足跡。(PS3 使用IBM的CDC VM)
2. Android裡的VM效能如何?
首先,Android裡的VM不能稱為JVM,因為整個軟體開發框架中,Java只存在於程式寫作階段,在deploy階段就已經被dx這個tool,把.class轉換成.dex,這是一種特殊的binary格式,類似class,但是其有更先進的設計架構。
Android的VM稱為Dalvik VM,它只執行.dex檔,並且搭配Zygote(Android OS中的process管理器,其會preload所有的系統library,每個獨立的Android程式有各自的process,但卻可以share同一份library,例如android.os.*,這樣可以節省runtime記憶體),以系統化的方式整合進Linux系統,因此DalvikVM相較於Sun實作的CDC/CLDC VM,有著更節省記憶體的優勢,這樣間接的讓整體系統運作速度變快很多。
此外,很有趣的是,當Sun不斷的以JIT為核心,甚至在CLDC VM中也有JIT時,Dalvik VM在第一時間卻不使用JIT技術。(註:Android 2.0 的dalvik已經有JIT implementation, for ARM)
原因無他,也是因為記憶體。
JIT compiler,就是compiler,其編譯bytecode(8位元指令)轉換為機器碼(16, 32 or 64位元指令),這對於整體native code size是增加的,因此JIT compiler其實在嵌入式系統裡的記憶體使用量反而是增加的且間接的造成運作效能下降。因此DalvikVM只使用Intepreter作為bytecode execution engine。
什麼,這樣用intepreter不是更慢?
現在有試用過HERO的人就知道,其順暢程度直逼iPhone 3G,其原因就是其利用Java programming API與JNI的優勢,把常使用的功能切出來,盡量使用JNI直接用C/C++實作,再包裝成Java API,提供AP實作使用,例如Camera, GPS, Telephony, UI等API,因此Android程式一開始的進入點是interpreter執行沒錯,但到後期幾乎都是native code在運作。透過API隔開耗時與較不穩定的功能邏輯,AP實作者與系統廠各自分責,所以Android程式/OS的效能與一般也具有多工背景執行的OS相比,穩定且快速許多。
總結
對Android解決了嵌入式 Java VM傳統的問題,但卻延展了Java的優點,並且以優異的SDK為核心,統一了整個device/AP/market供應鏈,對大家皆有利益。
當然Android也有許多缺點,例如
- Android Framework版本持續變動,讓AP開發者必須經常變動API的使用方式。
- Android Low Memory Killer號稱可以自動回收process,但實際上user還是需要手動砍,才能順暢使用
- APK的DRM問題目前只有Google自己有解決方案,若有其他人想做第三方market,DRM問題依舊存在,因為只用AP層解決安全性較低。