浅析dalvik虚拟机JIT技术的实现
浅析 dalvik 虚拟机 JIT 技术的实现
#移动开发 #Android
一、说明
据说 Android 2.2 的虚拟机 dalvik 使用了 JIT 技术,使其运行 速度快了 5
倍。dalvik
解释并执行程序,JIT 技术主要是对多次运行的代码进行编译,当再次调用时使用编译之后的机器码,而不是每次都解释,以节约时间。5
倍是测试程序测出的值,并不是说程序运行速度也能达到 5
倍,这是因为测试程序有很多的重复调用和循环,而一般程序主要是顺序执行的,而且它是一边运行,一边编译,一开始的时候提速不多,所以真正运行程序速度提高不是特别明显。
二、JAVA 虚拟机主要的优化技术
1. JIT(Just In Time) 最开始指在执行前编译,但是到现在已经发展成为,一开始解释执行,只有被多次调用的程序段才被编译,编译后存放在内存中,下次直接执行编译后的机器码
method 方式:以函数或方法为单位进行编译
trace 方式:以 trace 为单位进行编译(可以把循环中的内容作为单位编译),此方法也包含 method
2. AOT(Ahead Of Time) 在程序下载到本地时就编译成机器码,并存储在本地存在硬盘上,以加快运行程度,用此种方式,可执行的程序会变大四五倍
三、dalvik 中 JIT 的实现
每启动一个应用程序,都会相应地启动一个 dalvik 虚拟机,启动时会建立
JIT
线程,一直在后台运行。当某段代码被调用时,虚拟机会判断它是否需要编译成机器码,如果需要,就做一个标记,JIT
线程不断判断此标记,如果发现被设定就把它编译成机器码,并将其机器码地址及相关信息放入 entry table
中,下次执行到此就跳到机器码段执行,而不再解释执行,从而提高速度。
四、dalvik JIT 部分代码分析
android 2.2 代码还未发布,而 2.1 代码中已经加入 JIT
部分,只是默认未打开,以 2.1
代码为例对其原理进行分析,源码位置:$ANDROID_SRC/dalvik/vm/
1. 核心文件
vm/interp/Jit.c
供外界调用的入口vm/compiler/compiler.c
核心函数的实现vm/compiler/Frontend.c
编译 method 和 trace 的实现
2. 全局变量
- gDvmJit
所有与 JIT 相关的数据及结构都存储于此,各个程序通过它访问 JIT 资源
3. 开关
dvmCompilerStartup() (vm/compiler/Compiler.c) 在虚拟机启动时调用
dvmCompilerShutdown() (vm/compiler/Compiler.c) 在虚拟机关闭时调用
4. 线程
- compilerThreadStart() (vm/compiler/Compiler.c)
被 dvmCompilerStartup() 调用,在虚拟机运行过程中一直生存的线程,while
循环判断是否有代码需要编译,如果有,则调用 dvmCompilerDoWork() 对其进行编译
5. 编译成字节码
doCompilerdoWork() 又分 method 和 trace 两种情况进行编译
dvmCompilerMethod() (vm/compiler/Frongend.c)
dvmCompilerTrace() (vm/compiler/Frongend.c)
其中的:dvmCompilerMIR2LIR(),dvmCompilerAssembleLIR()(MIR 和 LIR
都是解释层的中间表示)逐层翻译成机器码
6. 编译后字节码的存储
- dvmcompilerSetupCodeCache() (vm/compiler/Compiler.c)
gDvmJit.codeCache:使用 mmap 分配(1024x1024),用于存在编译后的代码
gDvmJit.codeCacheByteUsed:codeCache 的使用情况
gDvmJit.codeCacheFull:codeCache 是否已写满
gDvmJit.pJitEntryTable:entry 表,每个 trace 对应一个 entry
7. 其它线程对 JIT 资源的访问
以下是一个示例,说明从主函数到 JIT 的调用关系如下:
AndroidRuntime::Start()->startVm()->_JNIEnv::CallStaticVoidMethod()->Check_CallStaticVoidMethodV()->CallStaticVoidMethodV()->dvmCallMethodV()->dvmInterpret()->dvmMterpStd()->dalvik_mterp()->Dalvik_java_lang_reflect_Method_invokeNative()->dvmInvokeMethod()->dvmInterpret()->dvmJitCheckTraceRequest()->dvmjitLookupAndAdd()
主要函数解释如下:
dvmJitLookupAndAdd()
判断是否有相对某段程序的字节码可用,如果有则返回其地址,如果没有,则做标记,以通知编译线程对其进行编译dvmCheckJit()
此函数被 define 成 CHECK_JIT(),它来判断什么条件时认为需要编译
(转载请注明出处:http://xy0811.spaces.live.com)