1 測試工具的實現
1.1 調研目的
目前正在進行針對Unicore架構的Dalvik虛擬機改寫,為了保證整個Android操作系統在Unicore上的正常運行,我們試圖先獨立測試改寫後的Dalvik虛擬機;而Android2.1源碼中包含了dalvik虛擬機的測試工具,其目錄位於/android2.1/dalvik/tests下,我們先對它進行調研,看能否用它來測試我們改寫後的dalvik虛擬機。
調研分為三部分進行,首先了解該測試工具的實現方式,其次介紹它的使用方法,最後評估用它測試修改後的dalvik虛擬機的可行性。
1.2 tests簡介
首先分析/android2.1/dalvik/tests目錄的結構:
-tests dalvik測試工具和測試代碼文件夾。
--001——078 文件夾,保存了78個測試代碼,主要由/src/*.java(測試所需代碼)
以及xpected.txt(測試期望結果文檔)和info.txt(測試說明文檔);
--ect 試工具的最終實現腳本,用Linux shell命令格式寫成;
--run-all-tests 執行文件,測試所有78個測試代碼;
--run-test 可執行文件,指定參數來測試特定的測試代碼。
1.3 測試工具的實現
通過上節的介紹,要理解測試工具是如何實現對dalvik虛擬機的測試,就必須理解run-test可執行文件(run-all-tests可以看做是逐一調用run-tests),下面將具體介紹該可執行文件的實現方式。
1.3.1 run-test的參數
1.3.1.1 綜述
進入/android2.1/dalvik/tests,在Linux shell下輸入命令:
./run-test –help
可以出現使用幫助,羅列並解釋如下:
run-test –help 打印幫助信息
run-test [options] [test-name] 正常運行命令的格式
run-test --dev [options] [test-name] 開發模式(運行結果dump到stdout)
run-test --update [options] [test-name] 更新模式(運行結果代替expect.txt)
運行參數:
--fast 使用快速解釋器(默認)
-jit 使用JIT
--portable 使用可移植的解釋器
--debug 等待調試器的連接
--no-verify 關閉校對功能(默認打開)
--no-optimize 關閉代碼優化功能(默認打開)
--no-precise 關閉精確GC功能(默認打開)
--zygote 從Zygote進程創建當前進程,如果使用,當前運行參數會被忽視
--local 使用主機-本地(host-local)模擬器
--valgrind 本地運行時使用內存監測
--reference 使用主機-本地參考(host-local reference)模擬器
通過幫助信息我們了解到,run-test有正常模式、開發模式、更新模式三種模式和多種參數,下面對參數的含義進行更詳細的說明,並評估了該參數對於我們使用本測試工具的價值,在下文中我們根據需要進一步調研一部分參數:
參數 含義 價值
fast dalvik的解釋器采用快速解釋器,與可移植型解釋器相對 高
jit android2.2開始采用的jit技術 低
portable dalvik解釋器采用可移植型解釋器,與快速解釋器相對 高
debug 調試用,等待調試器連接 高
verify dexopt的校對模式,dexopt用於dex代碼的優化 中
optimize dexopt的優化模式 中
precise GC管理的一個選項 低
zygote 直接從Zygote進程創建測試進程 中
local 使用local設備(不是host上的虛擬機)來測試 高
valgrind --local並且添加了內存管理的東西 低
reference 可使用host上的模擬器,模擬local設備的虛擬機進行測試 高
1.3.1.2 debug
該參數的幫助文檔是:等待調試器的連接(wait for debugger to attach)。為了使用該參數必須實現android的調試器(Debugger),dalvik虛擬機支持許多開發環境下的源碼級的調試,任何基於JDWP(Java Debug Wire Protocol)的遠程調試工具都可以,包括JDB、Eclipse、JSwat等。
首先,介紹該參數的實現原理。在本測試的腳本文件/android2.1/dalvik/tests/ect/push-and-run-test-jar(下文將解釋為什麼是這個)中可以看出,debug參數是通過以下命令才實現的:
代碼位置:/android2.1/dalvik/tests/ect/push-and-run-test-jar
源代碼:
調試參數設定:
if [ "$DEBUG" = "y" ]; then
DEX_DEBUG="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
fi
執行命令:
adb shell cd /data \; dalvikvm $DEX_VERIFY $DEX_OPTIMIZE $DEX_DEBUG \
$GC_OPTS -cp test.jar "-Xint:${INTERP}" -ea Main "$@"
參數解釋如下:
transport: 所使用的傳輸機制,dalvik支持TCP/IP socket、通過adb(dt_android_adb)訪
問USB的方式;
server: 決定虛擬機是作為服務器(server)還是客戶端(client),作為服務器時,虛擬機等待調試器連接,反之,虛擬機主動試圖連接調試器;
suspend: 如果是y,虛擬機在調試器連接之前不運行任何代碼,連接時,它會告訴調試器它掛起了,直到有新的指令它才會運行。
最終--debug的參數變為dalvikvm可執行文件的參���來執行。至於JDWP的工作原理,在此不展開討論。
下面,介紹--debug參數的具體使用方法(以在Linux下運行android模擬器、執行本測試方法第17號源碼為例進行介紹)。
1、在本地Linux環境啟動android模擬器
cd /android2.1/out/host/linux-x86/bin (添加了環境變量後就可以在任意目錄輸入emulator)
emulator
2、運行本測試工具
cd /android2.1/dalvik/tests
./run-test --debug 017
此時在shell下將顯示如下內容:
[seucr@android2 tests]$ ./run-test --debug 017-float/
/home/seucr/android2.1_r2/dalvik/tests/017-float: running...
(等待調試器連接)
3、運行DDMS
DDMS(Dalvik Debug Monitor Server)可以看做連接設備和JDWP調試器的橋梁,它顯示設備當前的進程、方法等內容,允許向設備發送命令,調試器可以通過它看到設備底層的PID號、進程號等內容。
cd /android2.1/out/host/linux-x86/bin
ddms
此時在DDMS界面上可以看到當前模擬器的運行狀態。由於此時已經在運行debug下的測試,因此在DDMS上可以看到一個進程名叫“?”,點擊它。
4、運行JDB調試
jdb -attach localhost:8700
此時shell會顯示如下內容:
[seucr@android2 bin]$ jdb -attach localhost:8700
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
>
VM Started: "thread=<3> main", dalvik.system.NativeStart.main(), line=-1 bci=-1
<3> main[1]
此時就已經進入了調試界面,通過help命令可以看到可執行的命令,包括run、step、stepi等很多。直接運行run可以跑完測試程序。
5、結果分析
最終的結果很有可能是測試FAILED(判斷依據下文將詳細敘述)。這是因為在執行build時前期會導致:
DDM dispatch reg wait timeout
Can't dispatch DDM chunk 52454151: no handler defined
錯誤,後來就可以正常運行,具體原因不詳。但是對比expect.txt和output.txt,可以看出期望的結果已經運行出來了。