Android脱壳基础知识

发布时间 2023-04-11 19:49:09作者: 奔跑的菜鸟Run

JVM的类加载器:

  1. Bootstrap ClassLoader 引导类加载器:C/C++代码实现的加载器,用于加载制定的JDK核心库,比如java.lang.*、java.util.*等这些系统类。Java虚拟机的启动就是通过Bootstrap,该ClassLoader在java里无法获取,负责加载/lib下的类
  2. Extensions ClassLoader 拓展类加载器:Java中的实现类为ExtClassLoader,提供了除了系统类之外的额外功能,可以在java里获取,负责加载/lib/ext下的类
  3. Application ClassLoader 应用程序类加载器:Java中的实现类为APPClassLoader,是与我们接触最多的类加载器,开发人员写的代码默认就是它来加载,ClassLoader.getSystemClassLoader返回的就是它。
  4. 自定义类加载器:只需要通过继承java.lang.ClassLoader类的方式来实现自己的类加载器即可。

加载器的加载顺序:

加载顺序:

  1. BootStrap ClassLoader
  2. Extension ClassLoader
  3. APPClassLoader

双亲委派

  如果一个类加载器收到了类加载请求,他并不会自己先去加载,而是把这个请求委托给父类加载器去执行,如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最终会到达顶层的启动类加载器,如果父类加载器可以完成加载任务,就成功返回,如果父类加载器无法完成加载任务,子加载器才会尝试去自己加载,这就是双亲委派模式,即每个儿子接到工作都会给父亲去干,当父亲干不了时,再自己去尝试干。

  双亲委派的存在原因:

  1. 避免重复加载,如果加载过一次Class,可以直接读取已经加载的Class
  2. 更加安全,无法自定义类来替代系统的类,可以防止核心API库被随意篡改

类加载时机:

  1. 隐式加载:
    • 创建类的实例来初始化某个类的子类
  2. 显式加载:通过反射来加载我们已知的类来加载:
    • 使用LoadClass()加载
    • 使用forName()加载

类加载流程:

  1. 装载:查找和导入Class文件
  2. 链接:其中解析步骤是可以选择的
    1. 检查:检查载入的class文件数据的正确性
    2. 准备:给类的静态变量分配储存空间
    3. 解析:将符号引用转成直接引用
  3. 初始化:即调用<clinit>函数,对静态变量,静态代码块执行初始化工作

  其中1、2步骤并未类中的函数进行任何调用

 

Android系统中的ClassLoader:

ClassLoader.java为抽象类,BootClassLoader是预加载常用类,单例模式。与Java中的BootClassLoader不同,它并不是用C/C++代码实现的,而是由Java实现的。

  SecureClassLoader继承了抽象类ClassLoader,拓展了ClassLoader类,加入了权限方面的功能,其子类URLClassLoader是由URL路径从jar文件中加载类和资源。

  BaseDexClassLoaderPathClassLoaderDexClassLoaderInMemoryDexClassLoader的父类,类加载的主要逻辑都是在BaseDexClassLoader中完成的。

    PathClassLoaderAndroid默认使用的类加载器,一个apk中的Activity等类便是其加载。

    DexClassLoader可以加载任意目录下的dex、jar、apk、zip文件,比PathClassLoader更灵活,是实现插件化、热修复以及dex壳的重点

    InMemoryDexClassLoader从内存中加载Dex文件