Android性能优化(6):浅析类加载机制与热修复技术

本文详细介绍了Android类加载机制,包括类加载器的层次结构、双亲委托模式和加载过程。此外,还探讨了Java反射机制。文章进一步讲解了Android热修复技术,分析了Tinker、QZone超级补丁、AndFix和Robust等方案,强调了热修复的即时生效和重启生效的区别,并提供了简化版热修复框架的实现思路。
摘要由CSDN通过智能技术生成

1. 类加载与反射

1.1 类加载机制

 类的加载是指将类的.class文件读入到内存中,并为之创建一个java.lang.Class对象,该过程由类加载器(ClassLoader)完成。类的加载过程包含类的加载类的连接类的初始化三个过程,当程序主动使用某个类时,如果该类还未被加载到内存中,系统就会通过这三个步骤来对该类进行初始化。因此,类的加载过程又可称为类的初始化过程,整个过程大致如下图所示:
在这里插入图片描述

1.1.1 类加载器

 类加载器负责将类的.class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。类加载器负责加载所有的类,一旦一个类被载入JVM中,同一个类就不会再次载入。类加载器通常无法等到首次使用该类时才加载类,Java虚拟机规范允许系统预先加载某些类,当然在Android中也会支持预先加载。由于Android虚拟机并没有遵循Java虚拟机规范,因此它们的类加载器并不相同,接下来我们具体分析。

1.1.1.1 Java中的ClassLoader

 Java中的类加载器主要由两种类型,即系统类加载器和自定义类加载器,其中,系统类加载器由Bootstap ClassLoader(引导类加载器)Extension ClassLoader(扩展类加载器)Application ClassLoader(应用程序类加载器)组成,而自定义类加载器为通过继承java.lang.ClassLoader类的方式实现。它们之间的"继承"关系为:
在这里插入图片描述
 需要注意的是,上述的“继承”关系并非我们理解的父类与子类继承关系,这里的“继承”是指类加载器的层级。因为引导类加载器是由C/C++编写,是JVM自带的类加载器,负责Java平台核心库,而扩展类加载器也没有继承引导类加载器,而是继承于java.lang.ClassLoader类,同理系统类加载器也不是继承扩展类加载器,也是继承于java.lang.ClassLoader类。接下来,我们通过一段代码来了解下一个Java程序需要用到几种类加载器。

public class MyClass {
   
    public static void main(String[] args) {
   
        // 获取当前类的类加载器
        ClassLoader classLoader = MyClass.class.getClassLoader();
        System.out.println(classLoader);
        // 遍历当前类的父加载器
        while (classLoader != null) {
   
            classLoader = classLoader.getParent();
            System.out.println(classLoader);
        }
        System.out.println("===========================");
        // 获取系统类加载器加载的路径
        System.out.println(System.getProperty("java.class.path"));
    }
}

打印结果如下:

sun.misc.Launcher A p p C l a s s L o a d e r @ 18 b 4 a a c 2 s u n . m i s c . L a u n c h e r AppClassLoader@18b4aac2 sun.misc.Launcher AppClassLoader@18b4aac2sun.misc.LauncherExtClassLoader@42a57993
null
===========================
E:\Environment\java\jdk1.8\jre\jre\lib\charsets.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\access-bridge-64.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\cldrdata.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\dnsns.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\jaccess.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\localedata.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\nashorn.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\sunec.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\sunjce_provider.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\sunmscapi.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\sunpkcs11.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\ext\zipfs.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\jce.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\jsse.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\management-agent.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\resources.jar;
E:\Environment\java\jdk1.8\jre\jre\lib\rt.jar;
E:\ComProject\TestProject\lib\build\classes\java\main;
E:\Environment\java\jdk1.8\lib\idea_rt.jar

 从打印的结果可知,MyClass类的类加载器为AppClassLoader,它的父加载器为ExtClassLoader,而ExtClassLoader的父加载器为BootstrapClassLoader。这里之所以讲ExtClassLoader的父加载器打印为null,那是因为BootStrapClassLoader由C/C++编写,并不是一个Java类,因此无法在java的代码中获取它的引用。

1.1.1.2 Android中的ClassLoader

 Java中的ClassLoader加载的是jar文件.class字节码文件,而Android虚拟机加载的是.dex字节码文件,因此Java中的ClassLoader是不能适用在Android中。与Java中的ClassLoader一样,Android中的ClassLoader也分为系统类加载器和自定义类加载器,其中系统类加载器主要包括三种,即BootClassLoaderPathClassLoaderDexClassLoader,需要注意的是,这三种系统类加载器均由Java实现,且它们的父类均为java.lang.ClassLoader类,它们的继承关系(注:这里是父类与子类之间的继承)如下:
在这里插入图片描述
接下来,我们重点分析下以下三种系统类加载器:

  • BootClassLoader

 BootClassLoader由Java实现,它继承于ClassLoader且是该类的内部类,是Android平台上所有ClassLoader的最终parent,其作用是是预加载常用类,比如Frament、Dialog、DownLoadManager等等。BootClassLoader预加载常用类的过程是在Android系统启动时完成的,具体来说是在Zygote进程启动过程中在ZygoteInit的main方法中被创建使用的。BootClassLoader的源码如下:

// Android8.0\libcore\ojluni\src\main\java\java\lang\ClassLoader$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);
    }
	// 根据指定类全路径名创建其Class对象
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
   
        return Class.classForName(name, false, null);
    }
    ...
}
  • PathClassLoader

 PathClassLoader继承于ClassLoader的实现类BaseDexClassLoader,它的作用为加载系统类和应用程序的类,它在SystemServer进程启动时被创建。由于PathClassLoader的构造方法中没有optimizedDirectory参数,因此不支持自定义解压dex文件存储路径,也就意味着PathClassLoader只能用于加载已经安装的apk的dex文件,这个dex文件在APK安装时会被存储到/data/dalvik-cache目录下,也就是说PathClassLoader只能加载/data/dalvik-cache目录中的dex文件。PathClassLoader源码如下:

// Android8.0\libcore\dalvik\src\main\java\dalvik\system\PathClassLoader.java
public class PathClassLoader extends BaseDexClassLoader {
   
    public PathClassLoader(String dexPath, ClassLoader parent) {
   
        super(dexPath, null, null, parent);
    }
    
    public PathClassLoader(String dexPath, String librarySearchPath, 
                           ClassLoader parent) {
   
        // optimizedDirectory默认为/data/dalvik-cache
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值