ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:83.51KB ,
资源ID:659883      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/659883.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(AndroidART运行时无缝替换Dalvik虚拟机的过程分析资料.docx)为本站会员(b****0)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

AndroidART运行时无缝替换Dalvik虚拟机的过程分析资料.docx

1、AndroidART运行时无缝替换Dalvik虚拟机的过程分析资料Android ART运行时无缝替换Dalvik虚拟机的过程分析Android 4.4发布了一个ART运行时,准备用来替换掉之前一直使用的Dalvik虚拟机,希望籍此解决饱受诟病的性能问题。老罗不打算分析ART的实现原理,只是很有兴趣知道ART是如何无缝替换掉原来的Dalvik虚拟机的。毕竟在原来的系统中,大量的代码都是运行在Dalvik虚拟机里面的。开始觉得这个替换工作是挺复杂的,但是分析了相关代码之后,发现思路是很清晰的。本文就详细分析这个无缝的替换过程。我们知道,Dalvik虚拟机实则也算是一个Java虚拟机,只不过它执行

2、的不是class文件,而是dex文件。因此,ART运行时最理想的方式也是实现为一个Java虚拟机的形式,这样就可以很容易地将Dalvik虚拟机替换掉。注意,我们这里说实现为Java虚拟机的形式,实际上是指提供一套完全与Java虚拟机兼容的接口。例如,Dalvik虚拟机在接口上与Java虚拟机是一致的,但是它的内部可以是完全不一样的东西。 实际上,ART运行时就是真的和Dalvik虚拟机一样,实现了一套完全兼容Java虚拟机的接口。为了方便描述,接下来我们就将ART运行时称为ART虚拟机,它和Dalvik虚拟机、Java虚拟机的关系如图1所示:从图1可以知道,Dalvik虚拟机和ART虚拟机都实

3、现了三个用来抽象Java虚拟机的接口: 1. JNI_GetDefaultJavaVMInitArgs - 获取虚拟机的默认初始化参数 2. JNI_CreateJavaVM - 在进程中创建虚拟机实例 3. JNI_GetCreatedJavaVMs - 获取进程中创建的虚拟机实例 在Android系统中,Davik虚拟机实现在libdvm.so中,ART虚拟机实现在libart.so中。也就是说,libdvm.so和libart.so导出了JNI_GetDefaultJavaVMInitArgs、JNI_CreateJavaVM和JNI_GetCreatedJavaVMs这三个接口,供外界

4、调用。 此外,Android系统还提供了一个系统属性persist.sys.dalvik.vm.lib,它的值要么等于libdvm.so,要么等于libart.so。当等于libdvm.so时,就表示当前用的是Dalvik虚拟机,而当等于libart.so时,就表示当前用的是ART虚拟机。 以上描述的Dalvik虚拟机和ART虚拟机的共同之处,当然它们之间最显著还是不同之处。不同的地方就在于,Dalvik虚拟机执行的是dex字节码,ART虚拟机执行的是本地机器码。这意味着Dalvik虚拟机包含有一个解释器,用来执行dex字节码,具体可以参考这个系列的文章。当然,Android从2.2开始,也包

5、含有JIT(Just-In-Time),用来在运行时动态地将执行频率很高的dex字节码翻译成本地机器码,然后再执行。通过JIT,就可以有效地提高Dalvik虚拟机的执行效率。但是,将dex字节码翻译成本地机器码是发生在应用程序的运行过程中的,并且应用程序每一次重新运行的时候,都要做重做这个翻译工作的。因此,即使用采用了JIT,Dalvik虚拟机的总体性能还是不能与直接执行本地机器码的ART虚拟机相比。 那么,ART虚拟机执行的本地机器码是从哪里来的呢?Android的运行时从Dalvik虚拟机替换成ART虚拟机,并不要求开发者要将重新将自己的应用直接编译成目标机器码。也就是说,开发者开发出的应

6、用程序经过编译和打包之后,仍然是一个包含dex字节码的APK文件。既然应用程序包含的仍然是dex字节码,而ART虚拟机需要的是本地机器码,这就必然要有一个翻译的过程。这个翻译的过程当然不能发生应用程序运行的时候,否则的话就和Dalvik虚拟机的JIT一样了。在计算机的世界里,与JIT相对的是AOT。AOT进Ahead-Of-Time的简称,它发生在程序运行之前。我们用静态语言(例如C/C+)来开发应用程序的时候,编译器直接就把它们翻译成目标机器码。这种静态语言的编译方式也是AOT的一种。但是前面我们提到,ART虚拟机并不要求开发者将自己的应用直接编译成目标机器码。这样,将应用的dex字节码翻译

7、成本地机器码的最恰当AOT时机就发生在应用安装的时候。 我们知道,没有ART虚拟机之前,应用在安装的过程,其实也会执行一次“翻译”的过程。只不过这个“翻译”的过程是将dex字节码进行优化,也就是由dex文件生成odex文件。这个过程由安装服务PackageManagerService请求守护进程installd来执行的。从这个角度来说,在应用安装的过程中将dex字节码翻译成本地机器码对原来的应用安装流程基本上就不会产生什么影响。 有了以上的背景知识之后,我们接下来就从两个角度来了解ART虚拟机是如何做到无缝替换Dalvik虚拟机的: 1. ART虚拟机的启动过程; 2. Dex字节码翻译成本地

8、机器码的过程。 我们知道,Android系统在启动的时候,会创建一个Zygote进程,充当应用程序进程孵化器。Zygote进程在启动的过程中,又会创建一个Dalvik虚拟机。Zygote进程是通过复制自己来创建新的应用程序进程的。这意味着Zygote进程会将自己的Dalvik虚拟机复制给应用程序进程。通过这种方式就可以大大地提高应用程序的启动速度,因为这种方式避免了每一个应用程序进程在启动的时候都要去创建一个Dalvik。事实上,Zygote进程通过自我复制的方式来创建应用程序进程,省去的不仅仅是应用程序进程创建Dalvik虚拟机的时间,还能省去应用程序进程加载各种系统库和系统资源的时间,因为

9、它们在Zygote进程中已经加载过了,并且也会连同Dalvik虚拟机一起复制到应用程序进程中去。关于Zygote进程和应用程序进程启动的更多知识,可以参考和这两篇文章。 即然应用程序进程里面的Dalvik虚拟机都是从Zygote进程中复制过来的,那么接下来我们就继续Zygote进程是如何创建Dalvik虚拟机的。从这篇文章可以知道,Zygote进程中的Dalvik虚拟机是从AndroidRuntime:start这个函数开始创建的。因此,接下来我们就看看这个函数的实现:cpp view plain copy 在CODE上查看代码片派生到我的代码片void AndroidRuntime:star

10、t(const char* className, const char* options) . /* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env) != 0) return; . /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */

11、 char* slashClassName = toSlashClassName(className); jclass startClass = env-FindClass(slashClassName); if (startClass = NULL) ALOGE(JavaVM unable to locate class %sn, slashClassName); /* keep going */ else jmethodID startMeth = env-GetStaticMethodID(startClass, main, (Ljava/lang/String;)V); if (sta

12、rtMeth = NULL) ALOGE(JavaVM unable to find main() in %sn, className); /* keep going */ else env-CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env-ExceptionCheck() threadExitUncaughtException(env); #endif . 这个函数定义在文件frameworks/base/core/jni/AndroidRuntime.cpp中。 AndroidRuntime类的成员函数

13、start最主要是做了以下三件事情: 1. 创建一个JniInvocation实例,并且调用它的成员函数init来初始化JNI环境; 2. 调用AndroidRuntime类的成员函数startVm来创建一个虚拟机及其对应的JNI接口,即创建一个JavaVM接口和一个JNIEnv接口; 3. 有了上述的JavaVM接口和JNIEnv接口之后,就可以在Zygote进程中加载指定的class了。 其中,第1件事情和第2件事情又是最关键的。因此,接下来我们继续分析它们所对应的函数的实现。 JniInvocation类的成员函数init的实现如下所示:cpp view plain copy 在CODE

14、上查看代码片派生到我的代码片#ifdef HAVE_ANDROID_OS static const char* kLibrarySystemProperty = persist.sys.dalvik.vm.lib; #endif static const char* kLibraryFallback = libdvm.so; bool JniInvocation:Init(const char* library) #ifdef HAVE_ANDROID_OS char default_libraryPROPERTY_VALUE_MAX; property_get(kLibrarySystemP

15、roperty, default_library, kLibraryFallback); #else const char* default_library = kLibraryFallback; #endif if (library = NULL) library = default_library; handle_ = dlopen(library, RTLD_NOW); if (handle_ = NULL) if (strcmp(library, kLibraryFallback) = 0) / Nothing else to try. ALOGE(Failed to dlopen %s: %s, library, dlerror(); return false; / Note that this is enough to get something like the zygote / running, we cant property_set here to fix this for the

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1