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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

Android运行时ART加载OAT文件的过程分析资料Word文档格式.docx

1、-zip-fd=) + MAX_INT_LEN; char zip_location_argstrlen(-zip-location=) + PKG_PATH_MAX; char oat_fd_argstrlen(-oat-fd= char oat_location_argstrlen(-oat-name= sprintf(zip_fd_arg, -zip-fd=%d, zip_fd); sprintf(zip_location_arg, -zip-location=%s, input_file_name); sprintf(oat_fd_arg, -oat-fd=%d, oat_fd); s

2、printf(oat_location_arg, -oat-location=%s, output_file_name); ALOGV(Running %s in=%s out=%sn, DEX2OAT_BIN, input_file_name, output_file_name); execl(DEX2OAT_BIN, DEX2OAT_BIN, zip_fd_arg, zip_location_arg, oat_fd_arg, oat_location_arg, (char*) NULL); ALOGE(execl(%s) failed: %sn, DEX2OAT_BIN, strerror

3、(errno); 这个函数定义在文件frameworks/native/cmds/installd/commands.c中。 其中,参数zip_fd和oat_fd都是打开文件描述符,指向的分别是正在安装的APK文件和要生成的OAT文件。OAT文件的生成过程主要就是涉及到将包含在APK里面的classes.dex文件的DEX字节码翻译成本地机器指令。这相当于是编写一个输入文件为DEX、输出文件为OAT的编译器。这个编译器是基于LLVM编译框架开发的。编译器的工作原理比较高大上,所幸的是它不会影响到我们接下来的分析,因此我们就略过DEX字节码翻译成本地机器指令的过程,假设它很愉快地完成了。 APK

4、安装过程中生成的OAT文件的输入只有一个DEX文件,也就是来自于打包在要安装的APK文件里面的classes.dex文件。实际上,一个OAT文件是可以由若干个DEX生成的。这意味着在生成的OAT文件的oatdata段中,包含有多个DEX文件。那么,在什么情况下,会生成包含多个DEX文件的OAT文件呢? 从前面一文可以知道,当我们选择了ART运行时时,Zygote进程在启动的过程中,会调用libart.so里面的函数JNI_CreateJavaVM来创建一个ART虚拟机。函数JNI_CreateJavaVM的实现如下所示:extern C jint JNI_CreateJavaVM(JavaVM

5、* p_vm, JNIEnv* p_env, void* vm_args) const JavaVMInitArgs* args = static_cast(vm_args); if (IsBadJniVersion(args-version) LOG(ERROR) Bad JNI version passed to CreateJavaVM: version; return JNI_EVERSION; Runtime:Options options; for (int i = 0; i optionsi; options.push_back(std:make_pair(std:string(

6、option-optionString), option-extraInfo); bool ignore_unrecognized = args-ignoreUnrecognized; if (!Runtime:Create(options, ignore_unrecognized) return JNI_ERR; Runtime* runtime = Runtime:Current(); bool started = runtime-Start();started) delete Thread:Current()-GetJniEnv(); delete runtime-GetJavaVM()

7、; LOG(WARNING) return JNI_OK; 这个函数定义在文件art/runtime/jni_internal.cc中。 参数vm_args用作ART虚拟机的启动参数,它被转换为一个JavaVMInitArgs对象后,再按照Key-Value的组织形式保存一个Options向量中,并且以该向量作为参数传递给Runtime类的静态成员函数Create。 Runtime类的静态成员函数Create负责在进程中创建一个ART虚拟机。创建成功后,就调用Runtime类的另外一个静态成员函数Start启动该ART虚拟机。注意,这个创建ART虚拟的动作只会在Zygote进程中执行,Syst

8、emServer系统进程以及Android应用程序进程的ART虚拟机都是直接从Zygote进程fork出来共享的。这与Dalvik虚拟机的创建方式是完全一样的。 接下来我们就重点分析Runtime类的静态成员函数Create,它的实现如下所示:bool Runtime:Create(const Options& options, bool ignore_unrecognized) / TODO: acquire a static mutex on Runtime to avoid racing. if (Runtime:instance_ != NULL) return false; Init

9、Logging(NULL); / Calls Locks:Init() as a side effect. instance_ = new Runtime;instance_-Init(options, ignore_unrecognized) delete instance_; instance_ = NULL; return true; 这个函数定义在文件art/runtime/runtime.cc中。 instance_是Runtime类的静态成员变量,它指向进程中的一个Runtime单例。这个Runtime单例描述的就是当前进程的ART虚拟机实例。 函数首先判断当前进程是否已经创建有一

10、个ART虚拟机实例了。如果有的话,函数就立即返回。否则的话,就创建一个ART虚拟机实例,并且保存在Runtime类的静态成员变量instance_中,最后调用Runtime类的成员函数Init对该新创建的ART虚拟机进行初始化。 Runtime类的成员函数Init的实现如下所示:Init(const Options& raw_options, bool ignore_unrecognized) . UniquePtr options(ParsedOptions:Create(raw_options, ignore_unrecognized); heap_ = new gc:Heap(optio

11、ns-heap_initial_size_, options-heap_growth_limit_, heap_min_free_, heap_max_free_, heap_target_utilization_, heap_maximum_size_, image_, is_concurrent_gc_enabled_, parallel_gc_threads_, conc_gc_threads_, low_memory_mode_, long_pause_log_threshold_, long_gc_log_threshold_, ignore_max_footprint_); jav

12、a_vm_ = new JavaVMExt(this, options.get(); Thread* self = Thread:Attach(main, false, NULL, false); if (GetHeap()-GetContinuousSpaces()0-IsImageSpace() class_linker_ = ClassLinker:CreateFromImage(intern_table_); else CreateFromCompiler(*options-boot_class_path_, intern_table_); Runtime类的成员函数Init首先调用P

13、arsedOptions类的静态成员函数Create对ART虚拟机的启动参数raw_options进行解析。解析后得到的参数保存在一个ParsedOptions对象中,接下来就根据这些参数一个ART虚拟机堆。ART虚拟机堆使用一个Heap对象来描述。 创建好ART虚拟机堆后,Runtime类的成员函数Init接着又创建了一个JavaVMExt实例。这个JavaVMExt实例最终是要返回给调用者的,使得调用者可以通过该JavaVMExt实例来和ART虚拟机交互。再接下来,Runtime类的成员函数Init通过Thread类的成员函数Attach将当前线程作为ART虚拟机的主线程,使得当前线程可以

14、调用ART虚拟机提供的JNI接口。 Runtime类的成员函数GetHeap返回的便是当前ART虚拟机的堆,也就是前面创建的ART虚拟机堆。通过调用Heap类的成员函数GetContinuousSpaces可以获得堆里面的连续空间列表。如果这个列表的第一个连续空间是一个Image空间,那么就调用ClassLinker类的静态成员函数CreateFromImage来创建一个ClassLinker对象。否则的话,上述ClassLinker对象就要通过ClassLinker类的另外一个静态成员函数CreateFromCompiler来创建。创建出来的ClassLinker对象是后面ART虚拟机加载加

15、载Java类时要用到的。 后面我们分析ART虚拟机的垃圾收集机制时会看到,ART虚拟机的堆包含有三个连续空间和一个不连续空间。三个连续空间分别用来分配不同的对象。当第一个连续空间不是Image空间时,就表明当前进程不是Zygote进程,而是安装应用程序时启动的一个dex2oat进程。安装应用程序时启动的dex2oat进程也会在内部创建一个ART虚拟机,不过这个ART虚拟机是用来将DEX字节码编译成本地机器指令的,而Zygote进程创建的ART虚拟机是用来运行应用程序的。 接下来我们主要分析ParsedOptions类的静态成员函数Create和ART虚拟机堆Heap的构造函数,以便可以了解AR

16、T虚拟机的启动参数解析过程和ART虚拟机的堆创建过程。 ParsedOptions类的静态成员函数Create的实现如下所示:ParsedOptions* Runtime:ParsedOptions: parsed(new ParsedOptions(); const char* boot_class_path_string = getenv(BOOTCLASSPATH); if (boot_class_path_string ! parsed-boot_class_path_string_ = boot_class_path_string;is_compiler_ = false; for

17、(size_t i = 0; options.size(); const std:string option(optionsi.first); if (StartsWith(option, -Xbootclasspath:) boot_class_path_string_ = option.substr(strlen().data(); else if (option = bootclasspath) boot_class_path_ = reinterpret_castconst std:vector*(optionsi.second); else if (StartsWith(option

18、, -Ximage:image_ = option.substr(strlen( else if (.) compileris_compiler_ = true;parsed-is_compiler_ &image_.empty() image_ += GetAndroidRoot();image_ += /framework/boot.art return parsed.release(); ART虚拟机的启动参数比较多,这里我们只关注两个:-Xbootclasspath、-Ximage和compiler。 参数-Xbootclasspath用来指定启动类路径。如果没有指定启动类路径,那么默

19、认的启动类路径就通过环境变量BOOTCLASSPATH来获得。 参数-Ximage用来指定ART虚拟机所使用的Image文件。这个Image是用来启动ART虚拟机的。 参数compiler用来指定当前要创建的ART虚拟机是用来将DEX字节码编译成本地机器指令的。 如果没有指定Image文件,并且当前创建的ART虚拟机又不是用来编译DEX字节码的,那么就将该Image文件指定为设备上的/system/framework/boot.art文件。我们知道,system分区的文件都是在制作ROM时打包进去的。这样上述代码的逻辑就是说,如果没有指定Image文件,那么将system分区预先准备好的fra

20、mework/boot.art文件作为Image文件来启动ART虚拟机。不过,/system/framework/boot.art文件可能是不存在的。在这种情况下,就需要生成一个新的Image文件。这个Image文件就是一个包含了多个DEX文件的OAT文件。接下来通过分析ART虚拟机堆的创建过程就会清楚地看到这一点。 Heap类的构造函数的实现如下所示:Heap:Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free, double target_utilization, size_t ca

21、pacity, const std:string& original_image_file_name, bool concurrent_gc, size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode, size_t long_pause_log_threshold, size_t long_gc_log_threshold, bool ignore_max_footprint) : . std:string image_file_name(original_image_file_name);image_f

22、ile_name.empty() space:ImageSpace* image_space = space:ImageSpace:Create(image_file_name); AddContinuousSpace(image_space); 这个函数定义在文件art/runtime/gc/heap.cc中。 ART虚拟机堆的详细创建过程我们在后面分析ART虚拟机的垃圾收集机制时再分析,这里只关注与Image文件相关的逻辑。 参数original_image_file_name描述的就是前面提到的Image文件的路径。如果它的值不等于空的话,那么就以它为参数,调用ImageSpace类的静

23、态成员函数Create创建一个Image空间,并且调用Heap类的成员函数AddContinuousSpace将该Image空间作为本进程的ART虚拟机堆的第一个连续空间。 接下来我们继续分析ImageSpace类的静态成员函数Create,它的实现如下所示:ImageSpace* ImageSpace:Create(const std: original_image_file_name) if (OS:FileExists(original_image_file_name.c_str() / If the /system file exists, it should be up-to-date, dont try to generate return space:

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

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