定义
加载so文件
加载dex/jar/apk文件
动态加载的基础就是classloader,一个app中至少需要两个classloader,一个用来加载系统本身的类:bootclassloader;另一个用来加载app本身需要的一些类:pathclassloader。
- 双亲代理模型
ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
if (parentLoader == null && !nullAllowed) {
throw new NullPointerException("parentLoader == null && !nullAllowed");
}
parent = parentLoader;
}
从代码中可以得出,在构造自己的classLoader时,需要提供一个ClassLoader类型的参数parentLoader,通过这种构造方式,可以将一个应用程序,乃至整个android系统中所有的classloader通过一个树连接到一起,这就是ClassLoader的双亲代理模型
- loadClass
android系统通过loadClass加载dex中的类。loadClass的实现如下
public Class<?> loadClass(String className) throws ClassNotFoundException {
return loadClass(className, false);
}
protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(className);
if (clazz == null) {
ClassNotFoundException suppressed = null;
try {
clazz = parent.loadClass(className, false);
} catch (ClassNotFoundException e) {
suppressed = e;
}
if (clazz == null) {
try {
clazz = findClass(className);
} catch (ClassNotFoundException e) {
e.addSuppressed(suppressed);
throw e;
}
}
}
return clazz;
}
从代码中可以看到,loadClass的代码逻辑是:
- 通过findLoadedClass判断将要被加载的类className是否已经被加载过,如果被加载过则返回结果,没有被加载则继续执行代码
- 如果类className没有被加载过,则查看它的父节点有没有加载这个类,如果有则返回结果,如果没有则继续
- 调用findClass方法查找类,查找到则返回结果,未查找到则抛出异常。
通过loadClass的代码逻辑可以看到,这整个是一个递归算法,首先查看自己是否加载过该类,然后查看父节点是否加载过这个类,通过递归可以遍历这个节点以上的所有节点。
DexClassLoader可以加载未安装的apk以及sd卡上的jar包,dex等
PathClassLoader只能加载系统中已经安装过的apk
DexClassLoader能够加载sd卡上的内容的原因是DexClassLoader可以自己指定optimizedDirectory为Null,而PathClassLoader则不能指定optimizedDirectory为空。
- 好处
根据前边的分析可以知道,类加载器 - 坏处