oat文件映射到虚拟内存以及类方法执行的全过程

一、映射OAT文件到内存并解析头部

在这里插入图片描述

若backend是Quick类型,那么会生成quick类型的机器指令。Quick类型的机器指令的函数依赖关系由JNI函数表描述,而不需要通过动态链接器进行重定位。

通过OatFile类的静态成员函数OpenElfFile来手动加载指定的OAT文件。这种方式是按照ELF文件格式来解析要加载的OAT文件的。

ElfFile::Open()将oat文件的elf头和program headers通过 mmap() 映射到虚拟内存空间。由OatFile::Setup函数解析这些头部信息,并将获得的信息存入对应的对象和成员变量中,主要是OatDexFile对象

begin_和end_这两个值比较关键,是Setup函数的主要依据。begin_指向的是映射到虚拟内存中的oatdata段(即OAT头)的起始地址,这个OAT头包括OAT实际内容的所有头部信息和DEX文件内容。end_则是虚拟内存中oatexec段的结束地址,在解析OAT头时用来验证数据的正确性。oatdata段的内容如下所示:
在这里插入图片描述

重点展示一下图中第3步,加载elf头和program headers
在这里插入图片描述

注:调用mmap()的时候仅仅申请一个vm_area_struct来建立文件与虚拟内存的映射,并没有建立虚拟内存与物理内存的映射。Linux并不在调用mmap()时就为进程分配物理内存空间,直到下次真正访问地址空间时发现数据不存在于物理内存空间时,触发Page Fault即缺页中断,Linux才会将缺失的Page换入内存空间.
mmap()仅分配一个虚拟内存区域,并不分配物理内存区域。根据文件系统类型,将vma->vm_ops设为对应的file_operations. 这里有个很关键的结构体const struct file_operations *f_op;它是文件驱动操作的入口,在open的时候,完成file_operations的绑定,open流程跟mmap类似。

谢谢这位仁兄的介绍和图
在这里插入图片描述

二、查找类方法的所有本地机器指令

在这里插入图片描述
Android系统将ART运行时抽象成一个Java虚拟机。JavaVM接口,与JNIEnv接口的FindClass函数通过 classname 去加载该类所有机器指令,返回到一个OatClass对象中。并且通过LinkCode为类中的每个类方法设置好 解释器入口点

然后GetStaticMethodID函数通过 名字和签名 去这个Class对象中查找对应的类方法,返回一个jMethodID值,它就是一个ArtMethod对象指针。ArtMethod对象里保存着机器指令。

为什么每个类方法需要一个解释器入口点?
在ART虚拟机中,并不是所有的类方法都是有对应的本地机器指令的,并且即使一个类方法有对应的本地机器指令,当ART虚拟机以解释模式运行时,它也需要通过解释器来执行。当以解释器执行的类方法在执行的过程中调用了其它的类方法时,解释器就需要进一步知道被调用的类方法是应用以解释方式执行,还是本地机器指令方法执行。为了能够进行统一处理,就给每一个类方法都设置一个解释器入口点。
抽象方法声明类中是没有实现的,必须要由子类实现。因此抽象方法在声明类中是没有对应的本地机器指令的,它们必须要通过解释器来执行

三、执行类方法的过程分析

在这里插入图片描述

找到类方法对应的ArtMethod对象后,通过CallStaticVoidMethod函数去执行。先创建一个ManagedStack类型的调用栈帧,然后获取类方法的解释器入口点,之后通过一个stub(汇编代码)去间接调用该入口点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值