Android热修复之路——ClassLoader详解

本文详细探讨了Android中的ClassLoader,包括其工作原理、双亲委托机制以及源码分析。着重讲解了BaseDexClassLoader如何处理dex文件加载,并介绍了如何利用ClassLoader实现热修复,通过调整Elements顺序达到替换系统类的效果,为热修复技术奠定了基础。
摘要由CSDN通过智能技术生成

1、ClassLoader简介

在应用程序打包成APK时,程序中所创建的类、导入和引用的类都会被编译打包成一个或多个的dex文件中,打包成的dex文件在使用中如何加载类?答案就在本篇主题ClassLoader中,ClassLoader从字面就可以知道它主要用于类的加载,当代码中需要调用某个类时,ClassLoader就会遍历所有的dex文件中的类并保存在集合中,然后从集合中加载指定的Class文件,最终转换成JVM中使用的类;

2、ClassLoader工作机制

  • Android中ClassLoader分类
  1. PathClassLoader:负责加载系统和apk中的类,context.getClassLoader获取到的就是PathClassLoader实例;
  2. DexClassLoader:负责加载外部类(jar或apk),也用于热修复方案的执行;如:修复的dex文件;
  3. BaseDexClassLoader:PathClassLoader 和 DexClassLoader的父类,主要的执行逻辑和文件的处理都在其中(后面会分析它的源码);
  4. BootClassLoader:继承与ClassLoader类,一般来说向上传递时最顶层就是BootClassLoader,它在Zygote进程启动开始时,在ZygoteInit.main()方法中执行资源预加载,此时会单例创建BootClassLoader对象,它在loadClass中直接调用findClass(),而findClass()中调用Class.classForName(name, false, null)查找类;
  • 获取ClassLoader的继承关系
var loader = classLoader
while (loader != null) {
   
      System.out.println(loader)
      loader = loader.parent
   }
  1. 获取输出的结果:PathClassLoader中parent为BootClassLoader,在PathClassLoader内部保存这base.apk和library的文件
2019-08-29 13:13:10.444 29022-29022/com.alex.kotlin.optimization I/System.out: dalvik.system.PathClassLoader
[DexPathList[
[zip file "/data/app/com.alex.kotlin.optimization-lLeC3751i-Krivn3eNgrYA==/base.apk"],
nativeLibraryDirectories=[/data/app/com.alex.kotlin.optimization-lLeC3751i-Krivn3eNgrYA==/lib/arm64, /system/lib64, /system/vendor/lib64]]]
2019-08-29 13:13:10.444 29022-29022/com.alex.kotlin.optimization I/System.out: java.lang.BootClassLoader@14d954f
  1. 源码继承关系
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 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!");
    }
}
  • ClassLoader 传递性
    虚拟机的加载策略:在触发虚拟机对类的加载时,虚拟机默认使用调用对象中的ClassLoader加载,而调用对象又被调用它的对象中的ClassLoader加载,按此传递最终执行到最上层的ClassLoader

  • 双亲委派机制

  1. 在每个ClassLoader中都持有其父类的引用,在加载类文件时,首先会判断当前ClassLoader中是否已经加载过此类,如果加载过从缓存中获取,否则调用其父类的加载器去查找,父类也会先检查自己的缓存然后再调用父类查找,直到调用到BootstrapClassLoader(它内部持有的父类为空),当BootstrapClassLoader没有找到会向下逐级触发子类ClassLoader的查找,直到发起者
  2. 双亲委托机制的好处:(1)先执行父类的查找,避免了同一个类的多次加载;(2)这种先从父类查找的机制,使程序无法修改和替代Java基础包中的类,提高程序的安全性

3、ClassLoader源码分析

  • loadClass():ClassLoader中加载类时调用loadClass(),代码中将双亲机制体现的淋漓尽致
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
   
        Class<?> c = findLoadedClass(name);  //查找是否加载过此类
        if 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值