1、Android中有哪几种ClassLoader?它们的作用和区别是什么?
ClassLoader是个抽象类,其具体实现的子类有 BaseDexClassLoader 和SecureClassLoader 。
SecureClassLoader 的子类是 URLClassLoader ,其只能用来加载
BaseDexClassLoade的子类是 PathClassLoader和DexClassLoader。
PathClassLoader是Android加载系统类和应用程序的类,如果是加载非系统应用程序类,则会加载data/app/目录下的dex文件以及包含dex的apk文件或jar文件,不管是加载那种文件,最终都是要加载dex文件,在这里为了方便理解,我们将dex文件以及包含dex的apk文件或jar文件统称为dex相关文件。
DexClassLoader是Android加载dex文件以及包含dex的apk文件或jar文件,也支持从SD卡进行加载,这也就是说DexClassLoader可以在应用未安装的情况下加载dex相关文件。因此,DexClassLoader是热修复的基础。
2、简述ClassLoader的双亲委托模型
从Java虚拟机的角度来说,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现(HotSpot虚拟机中),是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都有Java语言实现,独立于虚拟机外部,并且全部继承自java.lang.ClassLoader。
从开发者的角度,类加载器可以细分为:
(1)启动(Bootstrap)类加载器:负责将 Java_Home/lib下面的类库加载到内存中(比如rt.jar)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
(2)标准扩展(Extension)类加载器:是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将Java_Home /lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
(3)应用程序(Application)类加载器:是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径(CLASSPATH)中指定的类库加载到内存中。开发者可以直接使用系统类加载器。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,因此一般称为系统(System)加载器。
除此之外,还有自定义的类加载器,它们之间的层次关系被称为类加载器的双亲委派模型。
3、简述双亲委托模型在热修复领域的应用
热修复是一种包含信息的独立的累积更新包,通常表现为一个或多个文件。通过下面热修复的流程可以看出双亲委托模型是如何应用在热修复上面。
热修复详细的流程:
1.通过PathClassLoader 来加载自身App的dex,因为我们要修改自己的bug.
2.通过DexClassLoader来加载我们的补丁dex文件,这里面就是没有bug的dex.
3.反射两个classLoader的<DexPathList pathList;>,目的是拿到这个值.
4.接着我们来继续反射两个classloader中的pathList(注意:是两个!一个是我们自己应用的,另一个是我们补丁的,PathClassLoader和DexClassLoader都继承BaseDexClassLoader),DexPathList里面的<Element[] dexElements;>,没错还是拿到这个数组的值
5.合并两个反射到的Element 数组!这里是重中之重.我们需要把我们的补丁dex放在数组的最前面!
6.将合并的新的数组,通过Field重新设置到我们自身App的DexPathList->dexElements.没错!就是合并之后覆盖有bug那个loader的Element 数组!!
7.通过Android build-tools 中的dx命令打包一个没有bug的dex
注:假设你的App中有一个class A 出bug了,那么你就可以通过dx命令打包一个只有class A的dex文件.