动态加载

定义

  • 加载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的代码逻辑是:

  1. 通过findLoadedClass判断将要被加载的类className是否已经被加载过,如果被加载过则返回结果,没有被加载则继续执行代码
  2. 如果类className没有被加载过,则查看它的父节点有没有加载这个类,如果有则返回结果,如果没有则继续
  3. 调用findClass方法查找类,查找到则返回结果,未查找到则抛出异常。

通过loadClass的代码逻辑可以看到,这整个是一个递归算法,首先查看自己是否加载过该类,然后查看父节点是否加载过这个类,通过递归可以遍历这个节点以上的所有节点。
DexClassLoader可以加载未安装的apk以及sd卡上的jar包,dex等
PathClassLoader只能加载系统中已经安装过的apk

DexClassLoader能够加载sd卡上的内容的原因是DexClassLoader可以自己指定optimizedDirectory为Null,而PathClassLoader则不能指定optimizedDirectory为空。

  • 好处
    根据前边的分析可以知道,类加载器
  • 坏处

你可能感兴趣的:(动态加载)