ART 和 Dalvik
Android应用程序是运行在ART 和 Dalvik虚拟机上的,并且每一个应用程序对应有一个单独的Dalvik虚拟机。只不过这个虚拟机执行的是dex文件。
Dalvik虚拟机和java虚拟机有差不多的特性,差别在于前者执行的指令集是基于寄存器的,而后者是基于栈的。
DVM也是实现了JVM规范的一个虚拟器,默认使用CMS垃圾回收器,但是与JVM运行 Class 字节码不同,DVM 执行 Dex(Dalvik Executable Format)** ——专为 Dalvik 设计的一种压缩格式。Dex 文件是很多 .class 文件处理压 缩后的产物,最终可以在 Android 运行时环境执行。
而ART(Android Runtime) 是在 Android 4.4 中引入的一个开发者选项,也是 Android 5.0 及更高版本的默认 Android 运行时。ART 和 Dalvik 都是运行 Dex 字节码的兼容运行时,因此针对 Dalvik 开发的应用也能在 ART 环 境中运作。
dexopt与dexaot
dexopt 在Dalvik中虚拟机在加载一个dex文件时,对 dex 文件 进行 验证 和 优化的操作,其对 dex 文件的优化结果 变成了 odex(Optimized dex) 文件,这个文件和 dex 文件很像,只是使用了一些优化操作码。
dex2oat
ART 预先编译机制,在安装时对 dex 文件执行AOT 提前编译操作,编译为OAT(实际上是ELF文件)可执行 文件(机器码)。
ClassLoader类加载
ClassLoader介绍
任何一个 Java 程序都是由一个或多个 class 文件组成,在程序运行时,需要将 class 文件加载到 JVM 中才可以使 用,负责加载这些 class 文件的就是 Java 的类加载机制。ClassLoader 的作用简单来说就是加载 class 文件,提供 给程序运行时使用。每个 Class 对象的内部都有一个 classLoader 字段来标识自己是由哪个 ClassLoader 加载的。
双亲委托机制
概念
可以看到创建 ClassLoader 需要接收一个 ClassLoader parent 参数。这个 parent 的目的就在于实现类加载的双 亲委托。即: 某个类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类 加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
意义
1、避免重复加载,当父类加载器已经加载过了 子类加载器就没必要再加载一次。
2、安全性考虑 如果子类先加载 那我们写的代码就可以优先核心api调用 那就进行了篡改。
分析
可以看到在所有父ClassLoader无法加载Class时,则会调用自己的 findClass 方法。 findClass 在ClassLoader 中的定义为:
其实任何ClassLoader子类,都可以重写 loadClass 与 findClass 。一般如果你不想使用双亲委托,则重写 loadClass 修改其实现。而重写 findClass 则表示在双亲委托下,父ClassLoader都找不到Class的情况下,定义 自己如何去查找一个Class。而我们的 PathClassLoader 会自己负责加载 MainActivity 这样的程序中自己编写的 类,利用双亲委托父ClassLoader加载Framework中的 Activity 。说明 PathClassLoader 并没有重写 loadClass
,因此我们可以来看看PathClassLoader中的 findClass 是如何实现的。
热修复
PathClassLoader 中存在一个Element数组,Element类中存在一个dexFile成员表示dex文件,即:APK中有X个 dex,则Element数组就有X个元素。