Android成长系列之类加载

汇总:Android小白成长之路_知识体系汇总【持续更新中…】

目录

ClassLoader是什么

ClassLoader就是类加载器,虚拟机是无法直接加载class字节码文件的,需要通过ClassLoader将字节码文件经过一系列的处理,最终形成虚拟机可以直接读取的Class对象

类加载流程

类加载流程可以简单地总结为:

  • 加载:通过不同的ClassLoader把各个来源的Class字节码文件加载到内存中
  • 验证:验证加载进来的字节流是否符合虚拟机的规范,预防通过特殊处理生成的不规范字节流被加载进内存
    • 文件格式验证:验证字节流是否符合Class文件格式的规范,并能被当前版本的虚拟机处理,
    • 元数据验证和字节码验证:对字节码的语义分析和对数据流进行分析,确保代码逻辑正确
    • 符号引用验证:通过字符串形式描述的类是否存在,类的定义是否符合规范
  • 准备:为类变量(被static修饰的变量)分配内存和赋初值,这里的默认初始值不是我们代码里写的初值,而是java虚拟机根据类型赋的初值,例如int初值为0
  • 解析:将常量池的符号引用替换成直接引用,虚拟机把所有的类名、方法名、字段名等符号引用替换为具体的内存地址或偏移量
  • 初始化:对类变量进行初始化,主要执行静态变量的初始化,包括静态变量的赋值和静态初始化块的执行

双亲委托机制

  • 对于两个类,当且仅当两个类都来源于同一个Class文件,并且被同一个类加载器加载,虚拟机才认为它们是同一个类
  • 双亲委托机制:
    • 当前ClassLoader首先从自己的加载缓存中查询是否此类已加载过,如果已加载则直接返回此类
    • 如果在当前ClassLoader没加载过,则委托父类加载器去加载,父类加载器也采用同样的策略,先查看自己的缓存,没有则继续委托父类加载去加载,一直到最高层类加载器
    • 当所有父类加载器都没有加载的时候,再由当前的类加载器进行加载,并且把它放入自己的缓存中
  • 父类加载器并不是指当前ClassLoader的父类,而是指当前ClassLoaderparent字段所对应的类,
  • 双亲委托机制的作用:
    • 防止重复加载同一个Class:加载过的Class会被直接返回
    • 保证核心库的Class不被篡改:核心库的Class由高层父类加载器加载,即使我们自己更改了某个核心库的类并且使用类加载器加载,也会交由父类加载器加载,而父类加载器已经加载过此类,就会直接返回已加载过的,避免核心库被篡改
  • 破坏双亲委托机制方法:自定义ClassLoader,并重写loadClass方法,不按照双亲委托机制,实现自己的逻辑

Java中的ClassLoader

Android成长系列之类加载

  • BootstrapClassLoader:最顶层的加载类,主要加载核心类库,通常为JDK目录下的jre/lib里的类库进行加载
  • ExtensionClassLoader:它的父类加载器为BootstrapClassLoader,它主要对JDK目录下的jre/lib/ext目录里的类库进行加载,JAVA 9及其之后替换为PlatformClassLoader
  • AppClassLoader:应用程序类加载器,它的父类加载器为ExtensionClassLoader,负责加载应用程序CLASSPATH目录下的所有jarClass文件

Android中的ClassLoader

Android成长系列之类加载

  • 由于Android中加载的不再是Class文件,而是Dex文件,因此Android中没有ExtensionClassLoader和AppClassLoader
  • BootClassLoader :在系统启动时创建,在App启动时将其传进来,用于加载一些系统Framework层级需要的类
  • DexClassLoaderPathClassLoader:可以从目录中加载APK、DEX和JAR,这两者的差别是PathClassLoader没有将optimizedDirectory置为Null,也就是没设置优化后的存放路径。其实optimizedDirectory为null时的默认路径就是/data/dalvik-cache目录。PathClassLoader是用来加载Android系统类和应用的类。而DexClassLoader可以指定optimizedDirectory,但到了Android 8.0之后,这个字段被弃用了,也就是说DexClassLoader指定了optimizedDirectory也不起作用了

类加载应用场景

  • 热加载
  • 加密保护
上一篇:java自定义ClassLoader加载指定的class文件


下一篇:线程上下文类加载器