插件化阿里Atlas之ClassLoader

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

1.DelegateClassLoader

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

插件化阿里Atlas之ClassLoader_第1张图片
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。如下图:

插件化阿里Atlas之ClassLoader_第2张图片
BundleClassLoader

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

3.BundleClassLoader的类加载顺序

插件化阿里Atlas之ClassLoader_第3张图片
BundleClassLoader.findClass

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

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

4.DelegateClassLoader的类加载顺序

插件化阿里Atlas之ClassLoader_第4张图片
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加载

插件化阿里Atlas之ClassLoader_第5张图片
findLibrary

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

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

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

你可能感兴趣的:(插件化阿里Atlas之ClassLoader)