Android培训班(56)Dalvik虚拟机的入口点

<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } -->

要分析Dalvik虚拟机的代码,到底从那里开始比较好呢?从事软件开发人员都知道,每个程序都有生命周期,都有出生点,也就是程序的进入位置。像C语言里控制台程序是使用main函数作为入口点的,java程序也是使用main函数作为入口点。其实Dalvik虚拟机作为应用程序启动时,也是一样的从main函数开始。从Dalvik虚拟机源码目录dalvik/dalvikvm/Main.c文件,就可以看到入口函数,如下:

/*

* Parse arguments. Most of it just gets passed through to the VM. The

* JNI spec defines a handful of standard arguments.

*/

int main(int argc, char* const argv[])

{

JavaVM* vm = NULL;

JNIEnv* env = NULL;

JavaVMInitArgs initArgs;

JavaVMOption* options = NULL;

char* slashClass = NULL;

int optionCount, curOpt, i, argIdx;

int needExtra = JNI_FALSE;

int result = 1;

 

setvbuf(stdout, NULL, _IONBF, 0);

 

/* ignore argv[0] */

argv++;

argc--;

...

 

因此,当你编译Dalvik虚拟机作为linuxx86应用程序来运行时,就需要注意了,这里是它的入口。

 

也许你会问,为什么需要Dalvik虚拟机作为linuxx86应用程序运行,它不是在手机平台ARM里运行的吗?这个问题问得好,问到点子上了。其实Dalvik虚拟机作为linuxx86应用程序运行,是用来开发和调试使用的,当需要作为手机平台使用时,它不是从Main函数作为入口点。嵌入式的开发人员都知道,在一个资源有限平台里开发和调试,都是一件不容易的事情,需要花费很多时间,那么有没有更好的方法来开发和调试呢?答案是有的。就是利用目前x86的平台,这样可以使用x86大量的工具和资源,大大地提高开发效率,更容易调试系统的功能。在Dalvik虚拟机进行开发新功能时,可以先在x86的平台上运行和调试通过,然后再编译在ARM平台运行。我曾经修改这个虚拟机的代码后,再在系统里编译和运行,发觉刚刚编译整个平台的时间,就非常多,在4核的CPU4G内存的linux系统下,再利用make -j4等多核编译技术,也需要好几分钟,这样每修改几行代码,添加一些细小的功能,就需编译测试一次,付出的时间成本太多了,显然需要另找出路,那么就是使用x86平台方式生成应用程序来测试。还有另外一个问题,就是单步调试的功能,在ARM平台也是比较麻烦的事情,程序有时会跑飞等等。

 

下面再来分析另外一个入口点,就是androiddalvik虚拟机在ARM平台运行的入口点。它显然不会通过Main函数来加载的,而从初始化进程加载的服务Zygote开始的。从Zygote服务代码,可以看到下面代码:

runtime.start("com.android.internal.os.ZygoteInit",

startSystemServer);

这里根据命令行参数来创建Dalvik虚拟机,并从 com.android.internal.os.ZygoteInit开始运行,然后启动所有Dalvik虚拟服务。 这这里的runtime对象,就是类AppRuntime,而类AppRuntime继承类AndroidRuntime,那么类AndroidRuntime是何物呢?类AndroidRuntimeandroid平台核心框架里的代码,它是实现JNI的基石,也就是说所有Dalvik虚拟机里的应用程序要访问底层系统的功能,都是通过JNI来实现的。可以从下面的文件找到这个类:

frameworks/base/core/jni/AndroidRuntime.cpp

在这个文件里,可以看到上面调用函数 start的实现,如下:

/*

* Start the Android runtime. This involves starting the virtual machine

* and calling the "static void main(String[] args)" method in the class

* named by "className".

*/

void AndroidRuntime::start(const char* className, const bool startSystemServer)

{

LOGD("/n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<</n");

 

char* slashClassName = NULL;

char* cp;

JNIEnv* env;

 

blockSigpipe();

 

/*

* 'startSystemServer == true' means runtime is obslete and not run from

* init.rc anymore, so we print out the boot start event here.

*/

if (startSystemServer) {

/* track our progress through the boot sequence */

const int LOG_BOOT_PROGRESS_START = 3000;

LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,

ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));

}

 

const char* rootDir = getenv("ANDROID_ROOT");

if (rootDir == NULL) {

rootDir = "/system";

if (!hasDir("/system")) {

LOG_FATAL("No root directory specified, and /android does not exist.");

goto bail;

}

setenv("ANDROID_ROOT", rootDir, 1);

}

 

//const char* kernelHack = getenv("LD_ASSUME_KERNEL");

//LOGD("Found LD_ASSUME_KERNEL='%s'/n", kernelHack);

 

/* start the virtual machine */

if (startVm(&mJavaVM, &env) != 0)

goto bail;

 

/*

* Register android functions.

*/

if (startReg(env) < 0) {

LOGE("Unable to register all android natives/n");

goto bail;

}

 

从上面的代码片段里,可以看到调用函数startVm,这个函数就是创建Dalvik虚拟机,继续查看函数startVm的代码片段,可以发现下面一段:

/*

* Initialize the VM.

*

* The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.

* If this call succeeds, the VM is ready, and we can start issuing

* JNI calls.

*/

LOGD("JNI_CreateJavaVM Start.../n");

if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {

LOGE("JNI_CreateJavaVM failed/n");

goto bail;

}

LOGD("JNI_CreateJavaVM End/n");

 

result = 0;

 

在这段代码里,主要任务就是初始化Dalvik虚拟机,通过调用 JNI_CreateJavaVM函数来实现的,而 JNI_CreateJavaVM函数的实现,就是在文件Dalvik/vm/Jni.c里。

 

到这里,就已经把另一个入口点分析完成了,通过上面的学习可以知道不同的入口,是来源于现实开发的需要,通过这些大型代码工程,可以学习到很多开发技巧,提高效率的方法。

<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } A:link { so-language: zxx } -->

//QQ: 9073204 EMAIL:9073204@qq.com

//蔡军生  2011-06-19

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值