探索Dalvik移植技术秘密所在


  本文标签:Dalvik移植技术

  其实Dalvik是基于寄存器,而JVM 却是基于栈的,Dalvik移植技术可以将 Java .class 转换成 .dex 格式. 一个dex档通常会有多个.class  。由于dex有时必须进行最佳化,会使档案大小增加1-4倍,以ODEX结尾  。)

  本文档指导读者如何把Dalvik虚拟机移植到一个Linux平台上,本文档假定我们要移植的平台和目前android平台在代码架构上有一定的相似性,可以进行移植  。核心库的移植核心库的源代码主要在Dalvik/libcore和dalvik/vm/native这两个文件夹中  。核心库的源代码是用C语言和C++写成的  。

  因此在Linux环境下不需要更改  。核心库的代码很多都是来自Apache Harmony项目,但是也有一些是来自OpenSSL、zlb和ICU等项目,因此,为了虚拟机的运行,这些项目需要被移植到新平台上  。

  JNI Call Bridge 的移植DVM的运行库绝大部分都是用portable C编写的,其中的一个例外是JNI call bridge  。简单来说,它的作用是把一系列的整型值转变成各种类型的函数参数,并且调用函数  。这个调用过程必须符合C函数调用的约定  。

  为了简化移植,JNI Call Bridge在新平台上通常会使用开源的FFI库(我觉得,这种库,大概类似于java一样,具有通用性吧)  。但是,Dalvik移植技术运行不够快,也没有对平台做专门优化,所以,移植JNI Call Bridge首先应该重新写一个FFI库  。

  JNI Call Bridge代码在dalvik/vm/arch/*这个位置上,同时,基于FFI的版本(我觉得大概是在移植的时候的通用版本)在“generic”目录下  。每一种架构都有两个源文件,其中一个是定义了JNI Call Bridge函数,函数如下  。dvmPlatformInvoke是把argv所指向的值转化为符合C类型调用的值,而后调用我上面指出的函数,再把得到的返回值放入JValue* pReturn所指向的地方  。

  再用./rebuild重新生成文件,看一下在dalvik/vm/mterp/out目录下的InterpAsm-myarch.S文件,可以看到在dvmAsmInstructionStart后面的一个单块内有stub函数的256个拷贝   。如果你不用汇编的话,系统就会一直使用stub.S  。

  注意一下,每一个块开头都有一个a.balign 64 指令  。这个指令把处理程序扩展到64个字节  。同时也要注意到${opcode} text变成了操作码的名字,它是用来调用C执行的(就是dvmMterp_${opcode})

  stub.S的实际内容由你自己来定义  。看看armv5t或者x86项目实例下的entry.S和stub.S你就知道了  。如果你将要移植的系统和我们说的有些不一样,但大体相似,目前的大部分代码你都可以使用,只是需要修改一下某些指令  。具体可以看一下armv4t的移植你就清楚了  。

  该函数可能使用方法签名来决定如何处理函数中的相关值  。至于方法签名,它是一个短小的DEX签名,用一个字符对应一个返回值和一个参数  。而另外一个源文件(前面提过有两个源文件)则定义了一个32位的“hint”  。当相应的方法类型被加载时,hint值就会被计算出来  。

  作为“arginfo”参数进入dvmPlatformInvoke函数,hint可以用来dvmPlatformInvoke停止例如扫面函数的返回值、总体参数的大小,以及整形参数64字节条件测试的限制等的ASCII方法签名  。(我想hint应该是决定函数是否对返回值或者参数进行方法签名扫描)  。

  解释器的移植Dalvik移植技术虚拟机运行库含有两个解释器,分别是标以“移动型”和“快速型”  。移动型主大体上就是一个C函数,在任何装有GCC的系统上都应该可以被编译出来  。(如果你的机器没装有GCC,那么你应该停用“threaded”模块,因为这个模块依赖于GCC的goto语句的目录来执行的  。不清楚的话可以查找THREADED_INTERP的定义  。

  快速型使用手工汇编导致的碎片(??这里不懂)  。如果目前系统里没有解释器可用,那么系统就会从C stubs中生成一个解释器,这个解释器运行速度比移动型慢了很多,说它是快速解释器,实在是名不符实  。

  快速型在系统里是被默认使能的,如果源代码不支持快速型  。那么该如何默认使能移动型呢?这可以通过dalvik.vm.execution-mode system来实现  。例如  。你打入如下一行:如果用汇编语言重写解释器的话,解释器的效能应该会有一个明显的提高再加上相应平台专用架构的优化,dalvik可以用一个指令一次执行完毕(??这里也不懂)