Android插件化-Android解析ClassLoader

139 阅读2分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

1.ClassLoader的类型

Android中的ClassLoader类型和Java中的ClassLoader类型类似,也分为两种类型,分别是系统ClassLoader和自定义ClassLoader。其中系统ClassLoader主要有3种分别是BootClassLoader、PathClassLoader和DexClassLoader。

1.1 BootClassLoader

Android系统启动时会使用BootClassLoader来预加载常用类,与Java中的BootClassLoader不同,它并不是使用C/C++代码实现,而是由Java实现的,BootClassLoader代码如下:

class BootClassLoader extends ClassLoader {
 
    private static BootClassLoader instance;
 
    @FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
    public static synchronized BootClassLoader getInstance() {
        if (instance == null) {
            instance = new BootClassLoader();
        }
 
        return instance;
    }
 
    public BootClassLoader() {
        super(null);
    }
		
	...	
}	

BootClassLoader是ClassLoader的内部类,并继承自ClassLoader。BootClassLoader是一个单例类,需要注意的是BootClassLoader的访问修饰符是默认的,只有在同一个包中才可以访问,因此我们在应用程序中无法直接调用。

1.2 PathClassLoader

Android系统使用PathClassLoader来加载系统类和应用程序的类,代码如下:

public class PathClassLoader extends BaseDexClassLoader {
    public PathClassLoader(String dexPath, ClassLoader parent) {
        super((String)null, (File)null, (String)null, (ClassLoader)null);
        throw new RuntimeException("Stub!");
    }

    public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
        super((String)null, (File)null, (String)null, (ClassLoader)null);
        throw new RuntimeException("Stub!");
    }
}

PathClassLoader继承自BaseDexClassLoader,实现也都在BaseDexClassLoader中。

1.3 DexClassLoader

DexClassLoader可以加载dex文件以及包含dex的压缩文件(apk和jar文件),代码如下:

public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {
        super((String)null, (File)null, (String)null, (ClassLoader)null);
        throw new RuntimeException("Stub!");
    }
}

构造方法的4个参数:

  • dexPath:dex相关文件的路径,多个使用冒号分隔
  • optimizedDirectory:解压的dex文件存储路径,路径必须为内部存储路径,一般使用程序私有路径:/data/data/{package_name}/
  • librarySearchPath:包含c/c++库的路径集合,多个路径用分隔符分隔,可为null
  • parent:父加载器

DexClassLoader继承自BaseDexClassLoader,方法都在BaseDexClassLoader中。

2.ClassLoader的继承关系

可以看到上面一共有8个ClassLoader相关类,其中有一些和Java中的ClassLoader相关类十分类似,下面简单对它们进行介绍:

  • ClassLoader是一个抽象类,其中定义了ClassLoader的主要功能。BootClassLoader是它的内部类。
  • SecureClassLoader类和JDK8中的SecureClassLoader类的代码是一样的,它继承了抽象类ClassLoader。SecureClassLoader并不是ClassLoader的实现类,而是拓展了ClassLoader类加入了权限方面的功能,加强了ClassLoader的安全性。
  • URLClassLoader类和JDK8中的URLClassLoader类的代码是一样的,它继承自SecureClassLoader,用来通过URl路径从jar文件和文件夹中加载类和资源。
  • InMemoryDexClassLoader是Android8.0新增的类加载器,继承自BaseDexClassLoader,用于加载内存中的dex文件。
  • BaseDexClassLoader继承自ClassLoader,是抽象类ClassLoader的具体实现类,PathClassLoader和DexClassLoader都继承它。