当前位置:   article > 正文

Android 类加载器机制_android类加载机制

android类加载机制

类加载机制

概述

  • ClassLoader即类加载,虚拟机将描述类的数据从class字节码文件加载到内存,并对书籍进行 检验、转换解析和初始化,最新形成可以被虚拟机直接使用的Java代码
  • 主要作用:
    • 实现类的加载功能
    • 确保被加载类在虚拟机中的唯一性

ClassLoader加载流程

  • 当需要使用某个类时,JVM虚拟机就会加载它的Class文件,并创建对应的Class对象,将Class文件加载到虚拟机的内存里,这个过程称为类加载
  • 类从被加载到JVM虚拟机内存到被卸载,整个完整的生命周期包括:类加载 --> 验证 --> 准备 --> 解析 --> 初始化 --> 使用 --> 卸载 七个阶段,其中验证、准备、解析这三个部分统称为连接
  • 类加载流程比较复杂,虽然加载过程有复杂的五个步骤,但是除了加载以外,其他四部都是由JVM虚拟机控制的

在这里插入图片描述

  • 步骤一:加载:将外部的Class文件加载到JVM虚拟机内,并存储到方法区
  • 步骤二:验证:确保加载到Class文件里的信息符合JVM虚拟机要求
  • 步骤三:准备:为类变量分配内存,并设置类变量的初始化值(初始值通常为0,非开发者定义的值)
  • 步骤四:解析:将常量池内的符号引用转为直接引用,如hello()方法,hello是符号引用,地址值是直接引用
  • 步骤五:初始化:对类变量进行初始化

双亲委托机制

双亲委托机制即父委托机制,指多个类加载器之间存在父子关系,当一个类加载的过程中,它首先不回去加载,而是委托给父类去加载,父类又委托给父类,因此所有的类加载都会委托给顶层的父类即BoostrapClassLoader进行加载。

如果父类无法完成这个加载请求,子加载器才会尝试自己去加载。

优点

使用双亲委托机制,Java类随着它的类加载器一起具备类一种带优先级的层次关系。通过这种层次关系,可以避免类的重复加载,可以避免核心类被不同的类加载器加载到内存中造成冲突和混乱,保证了Java核心库的安全。

关键类说明

BootstrapClassLoader
  • 启动类加载器
  • 纯C++实现的类加载,没有对应的Java类
  • 主要加载<JAVA_HOME>/lib目录下的核心库
ExtClassLoader
  • 扩展类加载器
  • 类全名是sum.misc.Launcher#ExtClassLoader
  • 主要加载<JAVA_HOME>/lib/ext目录下的扩展类,如swing系列、内置js引擎、xml解析器
AppClassLoader
  • 应用程序类加载器
  • 类全名sum.misc.Launcher$AppClassLoader
  • 负责加载ClassPath所指定类库,开发者可以直接使用该类加载器

在这里插入图片描述

流程图说明

请添加图片描述

流程说明

当有一个Class文件要被加载时,暂时不考虑我们自定义类加载器。最先从AppClassLoader中检查是否加载过(每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等下次加载的时候就可以直接返回了),如果有加载过无需再加载,否则会获取父加载器,再调用父加载器的loadClass()检查是否加载过,同理类似递归调用;直到BootstrapClassLoder检查知否加载过,如果没有加载过则会下沉到子加载器处理。这时候如果子加载器不能加载则抛出ClassNotFoundException异常。

代码分析

双亲委托机制的代码流程在java.lang.ClassLoader#loadClass()

protected Class<?> loadClass(String name, boolean resolve) {
    Class<?> c = findLoadedClass(name);
    
    //检查类是否被加载过
    if (c == null) {
        try {
            //如果没有加载,调用父类的加载器
            if (parent != null) {
                c = parent.loadClass(name, false);
            } else {
                //父类加载器为空,使用默认的 启动类加载器
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
        }

        if (c == null) {
            //父类加载器无法加载,则调用自身的findClass()进行类加载
            c = findClass(name);
        }
    }
    return c;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Android中的类加载机制

区别

Java中的ClassLoader可以加载jar文件和Class文件,这一点再Android中不适用,Android加载的是dex文件,所以在需要重新设计ClassLoader相关类。

Androd中的ClassLoader和Java的ClassLoader相似,也分为两种类型,分别是系统ClassLoader和自定义ClassLoader。系统ClassLoader包含:BootClassLoader、PathClassLoader和DexClassLoader。

Android类加载器关键类说明

在这里插入图片描述

BootClassLoader
  • Android系统启动时会使用BootClassLoader来预加载常用类,与Java中的BootstrapClassLoader不同的是,它不是由C/C++代码实现,而是由Java实现
  • BootClassLoader是ClassLoader的一个内部类

PathClassLoader和DexClassLoader在Android8.0之后完全一样

PathClassLoader
  • 继承自BaseDexClassLoader
  • Android系统使用PathClassLoader加载系统类和应用程序的类,从语义上讲:加载内存中已经安装的apk中的dex文件
DexClassLoader
  • 继承自BaseDexClassLoader
  • 从语义上讲:可以加载内存以外的dex/apk/jar文件

流程图说明

请添加图片描述

热修复实现

代码下载

常用命令:

dx --dex --no-strict --ouput <生成的dex文件名> <class文件包名>

例子:
./dx --dex --no-strict --output /Users/limengge/dev/fixed-01.dex /Users/limengge/dev/fixed/
  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/247746
推荐阅读
相关标签
  

闽ICP备14008679号