[转]浅析dalvik虚拟机JIT技术的实现



一、  说明
据说Android 2.2的虚拟机dalvik使用了JIT技术,使其运行速度快了5倍。dalvik解释并执行程序,JIT技术主要是对多次运行的代码进行编译,当再次调用时使用编译之后的机器码,而不是每次都解释,以节约时间。5倍是测试程序测出的值,并不是说程序运行速度也能达到5倍,这是因为测试程序有很多的重复调用和循环,而一般程序主要是顺序执行的,而且它是一边运行,一边编译,一开始的时候提速不多,所以真正运行程序速度提高不是特别明显。

二、  JAVA虚拟机主要的优化技术

1.          JIT(Just In Time)
最开始指在执行前编译,但是到现在已经发展成为,一开始解释执行,只有被多次调用的程序段才被编译,编译后存放在内存中,下次直接执行编译后的机器码

1)         method方式:以函数或方法为单位进行编译

2)         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.          核心文件

1)         vm/interp/Jit.c
供外界调用的入口

2)         vm/compiler/compiler.c
核心函数的实现

3)         vm/compiler/Frontend.c
编译method和trace的实现

2.          全局变量

1)         gDvmJit
所有与JIT相关的数据及结构都存储于此,各个程序通过它访问JIT资源

3.          开关

1)         dvmCompilerStartup() (vm/compiler/Compiler.c)      在虚拟机启动时调用

2)         dvmCompilerShutdown()      (vm/compiler/Compiler.c)      在虚拟机关闭时调用

4.          线程

1)         compilerThreadStart()  (vm/compiler/Compiler.c)
被dvmCompilerStartup() 调用,在虚拟机运行过程中一直生存的线程,while循环判断是否有代码需要编译,如果有,则调用dvmCompilerDoWork()对其进行编译

5.          编译成字节码
doCompilerdoWork()又分method和trace两种情况进行编译

1)         dvmCompilerMethod()         (vm/compiler/Frongend.c)

2)         dvmCompilerTrace()    (vm/compiler/Frongend.c)
其中的:dvmCompilerMIR2LIR(),dvmCompilerAssembleLIR()(MIR和LIR都是解释层的中间表示)逐层翻译成机器码

6.          编译后字节码的存储

1)         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()
主要函数解释如下:

1)         dvmJitLookupAndAdd()
判断是否有相对某段程序的字节码可用,如果有则返回其地址,如果没有,则做标记,以通知编译线程对其进行编译

2)         dvmCheckJit()
此函数被define成CHECK_JIT(),它来判断什么条件时认为需要编译


(转载于:http://xy0811.spaces.live.com)

猜你喜欢

转载自ahao99.iteye.com/blog/1859285