插件化阿里Atlas之ClassLoader

作者: dengyin2000 | 来源:发表于2017-03-27 01:36 被阅读697次

    Atlas插件框架整体设计参考了OSGI,而在OSGI中每一个Bundle会有一个自己的ClassLoader,所以我们需要了解下Atlas中的ClassLoader是怎样设计的,要不然可能经常会遇到ClassNotFoundException。

    1.DelegateClassLoader

    DelegateClassLoader的初始化是在android.taobao.atlas.framework.Atlas#init方法中,如下图:

    DelegateClassLoader初始化
    ① 这里获取当前的ClassLoader是PathClassLoader,这个也是安卓中默认的ClassLoader。
    ② new一个新的DelegateClassLoader,构造函数传入的是当前的PathClassLoader,也就是DelegateClassLoader的parent ClassLoader。
    ③ AndroidHack.injectClassLoader(packageName, newClassLoader)方法是把DelegateClassLoader注入到LoadedApk.mClassLoader。这样的话,当发生查找四大组件时就会使用DelegateClassLoader来加载

    2. BundleClassLoader

    BundleClassLoader的初始化是在new 每一个BundleImpl中,也就是说会为每个Bundle生成一个BundleClassLoader。如下图:

    BundleClassLoader

    ① 在BundleImpl类的resolveBundle方法中生成BundleClassLoader。
    ② BundleClassLoader的父类是BootClassLoader。

    3.BundleClassLoader的类加载顺序

    BundleClassLoader.findClass

    因为BundleClassLoader的parent是BootClassLoader,根据ClassLoader的双亲委托模式,查找顺序如下:

    1. BootClassLoader。
    2. findOwnClass,查找Bundle中的class。
    3. PathClassLoader,宿主apk中的class。
    4. 当前bundle依赖的bundles中的class。

    4.DelegateClassLoader的类加载顺序

    DelegateClassLoader.findClass

    loadFromInstalledBundles这个方法就是通过className找到对应的Bundle,然后再通过BundleClassLoader加载这个class的过程。DelegateClassLoader的parent是PathClassLoader,所以查找顺序如下:

    1. PathClassLoader,宿主apk中的class。
    2. 然后就是经过BundleClassLoader的类加载顺序。

    之前在使用Atlas中发现,Bundle加载完成之后,在宿主代码中通过Class.forName是找不到Bundle中的class就是这个原因。

    5.补充下bundle的so加载

    findLibrary

    ① 从宿主系统Path路径中查找。
    ② 如果没找到,则在当前bundle中的so中查找。

    所以对于so的加载,插件也是优先加载宿主的so,然后才是加载插件中的so。宿主是加载不到插件中的so的。

    Reference:http://atlas.taobao.org/docs/principle-intro/Runtime_principle.html

    相关文章

      网友评论

        本文标题:插件化阿里Atlas之ClassLoader

        本文链接:https://www.haomeiwen.com/subject/scjlottx.html