art虚拟机将dex编译成ota后,生成oat文件,该文件结构包含如下几部分
1 header 部分,记录一些meta信息(其实header是包含在oatdata部分的,可以通过导出部分找到对应的oatdata,也就可以找到队一个的header部分)
2 oatdata部分,保存各个原始dex信息
3 oatexec部分,保存dex经过llvm编译后的机器代码
4 导出符号部分,用于dlopen解析符号,找到oatdata部分
oat文件分为两种格式,一种是dlfile这种格式可以通过动态链接的方式导入符号,
另外一种是google自定义的格式Elffile,这种格式记录的信息更多,
所以不用动态去加载其他库的导出符号,因为其他库的导出符号会被记录在这个oat文件中
加载oat文件会建立oatdata和oatexec之间的关系,也就是原始dex和编译后的机器码之间的关系,
这样在链接的时候(classload).就可以根据dex的java类信息找到相应的oat了以及该类下的方法字段等.
AndroidRutime启动art的时候,首先会加载运行时环境,相当于jvm中BootClassLoader加载路径下的jar文件,
art创建是时候首先会创建JavaVMExt(用于记录虚拟机的全局信息),也就是实现jni时候经常要传递的参数,
然后创建虚拟机执行的主线程,也就是当前线程,之后为这个线程创建JNIEnvExt(env),该变量也是jni函数必然
传递的参数,env是每个java虚拟机线程一份的.用于传递虚拟机的运行时环境,已经java虚拟机的提供jni调用的方法,
这些方法来自于jin_internal.cc中的 JNI类实现,由此可见,要先hook住java世界可以从这里入手.
启动之后就会加载运行时换件,也就是运行时必须的oat,里面包括Integer等基本类型和Object等以及Android系统的定义的一些类.
加载这些类的过程:
首先判断当前线程的classLoader,由于刚刚启动,所以classloader自然没有设置,所以使用BootClassLoader加载,其实这个加载器并不存在,就是
使用classlinker类进行加载,大家都应该清楚类加载的过程是 findclass->defineclass->loaderclass
首先findclass 会根据方法的棕量以及classloader(这两个信息是定位一个类的唯一标示),去javaenv中维护的一个类加载信息表中,查找该类是否被加载,
如果已经被加载则直接返回,如果没有加载,就去dex_cache中查找(dex_cache还有个机制,如果缓存的类超过一个数量就会刷新到env的类加载信息表中 ),
如果找到就直接返回,如果没有找到就会去classpath中去查找,classpath其实就是指oatdata中的dex原始信息,在classpath如果也找不到相应的类,则会抛出异常.
找到之后就可以进行defineclass,其实defineclass的主要作用就是调用loadclass,loadclass 会根据dex文件中的索引信息找到对应的oatexec中的类机器码,之后填充kclass(kclass oop模型),
kclass包括字段信息,方法信息等.kclass完成之后类就被加载完成了
网友评论