dalvik 调试

本文档详细介绍了Dalvik虚拟机的测试工具及其使用方法,包括测试工具的实现原理、参数配置、运行流程和结果分析等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://hi.baidu.com/seucrcr/item/87835ec3c4c78351bcef6977

Dalvik——tests工具学习文档1

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,可以看出期望的结果已经运行出来了。


1.3.2 run-test的实现——基础
run-test可执行文件是一个Linux Shell的脚本文件,下面分析它的执行流程,从而调研本测试工具是如何测试dalvik虚拟机的。
run-test的执行流程图如下所示:



对于我们使用run-test来说,没有必要详细介绍内部的信息传递机制、具体参数的含义,只需要了解到它是怎么实现对dalvik虚拟机的测试的,下面具体就最后一个模块“选择要执行的脚本”来进行阐述。
我们以使用默认的不含运行时参数的run-test命令为例进行介绍:

代码位置:/android2.1/dalvik/tests/run-test 第218——230行
其代码可简化为如下流程图:


从这张流程图中可以清晰地看到执行的过程和判断的依据,但是又会产生两个疑问:这样为什么就能测试dalvik虚拟机了呢?宏build和run又是怎样、是在哪儿执行的呢?

1.3.3 run-test的实现——进阶
1.3.3.1 测试dalvik原理
首先解决第一个疑问,为什么这样就能测试dalvik虚拟机。
dalvik虚拟机的作用包括两部分:解释和运行。解释是将android应用程序、framework层等处所用的JAVA代码解释为.dex格式,运行是通过dalvik虚拟机来执行该.dex文件。如果有本地调用则通过JNI Call Bridge来解决。而上述流程图中可以明显看出,run-test可执行文件正是重复了dalvik虚拟机的工作,并且将当前dalvik虚拟机的代码运行结果和标准android2.1的dalvik虚拟机的运行结果比对从而判断虚拟机能否正常运行。
下图表示了android对于*.java的处理流程,可以粗略表征dalvik虚拟机的工作流程。



1.3.3.2 run-test最终实现方式
下面解决第二个问题:宏build和run又是怎样、是在哪儿执行的呢?
在run-test中有如下定义:

代码位置:/android2.1/dalvik/tests/run-test
源代码:
39      export JAVA="java"
export JAVAC="javac -target 1.5"
export RUN="${progdir}/etc/push-and-run-test-jar"
44    build="build"
run="run"
192    if [ '!' -r "$build" ]; then
       cp "${progdir}/etc/default-build" build
fi
if [ '!' -r "$run" ]; then
       cp "${progdir}/etc/default-run" run
fi
从这里可以清晰地看出,最终执行没有运行时参数的run-test的宏build和run的是/tests/ect/default-build和/tests/ect/default-run(其实是/tests/ect/push-and-run-test-jar)脚本文件。其中default-build将.jar转化为.dex(解释的功能),default-run将执行push-and-run-test-jar脚本,它通过如下语句来实现dalvik的运行功能:

代码位置:/android2.1/dalvik/tests/ect/push-and-run-test-jar
源代码:
108    adb push test.jar /data
       adb push test-ex.jar /data
130    adb shell cd /data \; dalvikvm $DEX_VERIFY $DEX_OPTIMIZE $DEX_DEBUG \
          $GC_OPTS -cp test.jar "-Xint:${INTERP}" -ea Main "$@"
这里也就解释了宏build和run事实上是在一个运行android的镜像的ARM设备(device)上执行的,因为它必须要执行adb shell、adb push,必须要执行镜像根目录下的/system/bin/dalvikvm可执行文件来解析.jar,而在当前dalvikvm是基于ARM架构编译出来的,在本地(host)上是不可执行的文件。

1.3.4 测试源代码
测试代码并不是没有针对性的任意JAVA程序,其组成都有如下规律:
1、代码结构:
--src   保存了源代码
   -Main.java   执行的java代码(有点像C里面的main()函数的意思)
   -*.java    Main.java要调用的其他方法(面向对象而已)
--expect.txt   保存了android2.1的官方dalvik运行Main.java的结果
--info.txt    介绍了这个测试的内容
--src2 少数有,用于在更换了编译生成了.class文件导致的“API不匹配”情况处理
2、代码测试目标明确,分门别类地测试了参数设定、参数传递、进程管理、指针、线程、gc等等各个方面,通过查看哪个代码测试结果和expect.txt不同,可以了解到dalvik虚拟机在处理哪方面问题上有错误。

2 测试工具的使用

2.1 测试工具在ARM设备上的使用方法
2.1.1 使用条件
从1.3.3节的分析可知,本测试工具的使用目前必须有以下两个条件:
1、 有ARM架构的android设备或者本地虚拟机(?可能由--local参数决定);
2、 在Linux环境下可连接到该设备;
其中第一个条件是由/android2.1/dalvik/tests/ect/push-and-run-test-jar中的adb命令、dalvikvm可执行文件(android整体编译生成,目前TARGET-ARCH为ARM)决定的,对于将.java解释为.dex是否需要设备还没有进行测试,第二个条件是由/android2.1/dalvik/tests/下的脚本文件写法决定的,它使用了Linux shell,因此只能在Linux下执行,不能在windows下运行该脚本。

2.1.2 使用方法
根据上述条件,可以写出本测试工具的使用流程。
1、进入android2.1目录,编译android源码

cd /USERDIR/android2.1
make
编译结束后,进入/out/target/product/generic/system/bin,查看是否生成了dalvikvm,如果没有,编译错误,重新检查并编译。
2、在本地Linux环境android模拟器上测试其虚拟机(可省略,直接做第三步,但不推荐)
(1)启动模拟器

cd /out/host/linux-x86/bin      (添加了环境变量后就可以在任意目录输入emulator)
emulator
(2)进入/android2.1/dalvik/tests/目录,shell下输入:

./run-test 代码文件夹名称   测试指定文件夹的代码
./run-all-tests      测试整个tests的78个代码
即可运行本测试工具。
在本模式下可以用的参数包括—fast、--portable、--no-verify、--no-optimize和--reference,--debug和--zygote没有测试,--local、--vargrind不可用。
3、在ARM架构的android设备上测试其虚拟机
(1)连接Linux环境(VMware虚拟机、Linux操作系统等等)到外部android设备。该步方法不统一,但衡量标准是,能在Linux下敲adb shell能连接到该设备。
(2)进入/android2.1/dalvik/tests/目录,shell下输入:

./run-test 代码文件夹名称   测试指定文件夹的代码
./run-all-tests      测试整个tests的78个代码
即可运行本测试工具。

2.1.3 测试结果分析
对于任何一个测试,评判测试成功与否的标准是对比android2.1官方dalvik运行该测试代码的结果(expect.txt)和用户dalvik运行测试代码的结果(output.txt)是否相同。
如果结果相同,则测试成功,会在shell下显示

android2.1_r2/dalvik/tests/代码文件夹名称: succeeded!
如果结果不相同,则测试失败,会在shell下显示

/android2.1_r2/dalvik/tests/017-float: FAILED!
#################info
CONTENT 测试内容
#################diffs
--- expect.txt        2010-06-23 08:58:55.000000000 +0800
+++ output.txt 生成时间
CONTENT 不同的地方
#################

file left in /tmp/test-NUM 测试生成的东西
根据这些可以找出哪里不同,从/tmp/test-NUM(/是LINUX的根目录)文件夹下可以查看到dalvik运行的结果,更方便查处错误的所在。需要注意的是,不是报FAILED错就代表着dalvik有问题。例如浮点运算会和具体硬件有关,测试结果和expect.txt很有可能不同,因此如果发现错误,需要逐个分析再对dalvik功能下结论。

3 后记

         本测试工具的使用必须是在android设备运行起来、能使用adb和dalvikvm可执行文件的情况下, 对该设备的虚拟机工作功能正确性进行测试。因此,本测试应该是放在dalvik修改工作的最后进行。





Android虚拟机Dalvik完整源码,宝贵资源,欢迎下载! This directory contains the Dalvik virtual machine and core class library, as well as related tools, libraries, and tests. A note about the licenses and header comments --------------------------------------------- Much of the code under this directory originally came from the Apache Harmony project, and as such contains the standard Apache header comment. Some of the code was written originally for the Android project, and as such contains the standard Android header comment. Some files contain code from both projects. In these cases, the header comment is a combination of the other two, and the portions of the code from Harmony are identified as indicated in the comment. Here is the combined header comment: /* * Copyright (C) The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ---------- * * Portions of the code surrounded by "// BEGIN Harmony code" and * "// END Harmony code" are copyrighted and licensed separately, as * follows: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Native SH call bridge --------------------- Native SH call bridge is written by Shin-ichiro KAWASAKI and Contributed to Android by Hitachi, Ltd. and Renesas Solutions Corp.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值