热修复预备知识

前期预备知识

dex/class

  1. class文件结构解析
    • 什么是class文件?

      能够被jvm识别,加载并执行的文件格式

    • 如何生成一个class文件

      • [x] 通过IDE自动帮我们build
      • [x] 手动通过javac 去生成class文件
        PS: 如何制定jdk版本生成字节码文件呢?—>javac -target 1.6 -source 1.6 HelloWorld.java
      • [x] 通过java命令去执行class文件
        java com.example.hostfit.Test ps: 执行时根据全类名来执行的
    • class文件的作用 记录类文件的所有信息(记录了this super 等关键字)

    • class文件结构及格式(宏观)

      • 一种八位字节的二进制流文件
      • 各个数据按照顺序紧密排列,无间隙
      • 每个类或接口都单独占一个class文件
    • class文件弊端

      • 内存占用大,不适合移动端
      • 堆栈加载模式,加载速度慢
      • 文件IO操作多,类查找慢
  2. dex文件结构解析
    • 什么是dex文件

      被DVM虚拟机识别,加载并执行的文件格式

    • 如何生成dex文件

      • [x] 通过IDE自动帮我们build生成
      • [x] 手动通过dx命令去生成dex文件
        • javac -target 1.6 -source 1.6 Test.java 生成class文件。ps:指定1.6 版本为了保证兼容
        • dx --dex --output=Test.dex com/example/hostfit/Test.class ps: 是根据全类名来找的
      • [x] 手动运行dex文件在手机上
        • 将dex文件push 到手机存储卡中 adb push Test.dex '手机路径(例如:/sdcard)'
        • dalvikvm -cp Test.dex com.example.hostfit.Test ps: 注意全类名
    • dex文件的作用

      记录整个工程中所有类文件的信息。

    • dex文件结构、格式的详解

      • 一种八位字节的二进制流文件
      • 各个数据按照顺序紧密排列,无间隙
      • 整个应用中所有的java源文件都放在一个dex文件中 ps: 不考虑android 官方提供的multidex
  3. class 与 dex 文件对比
    • 本质上他们都是一样的,dex文件从class文件演变而来
    • class文件存在许多冗余信息(一个类就有一个常量池),而dex文件会去除冗余,并进行整合

jvm/dvm/art 三种虚拟机

  1. java 虚拟机结构解析

    • jvm整体结构

    • java代码的编译和执行过程

      • 代码编译过程

      • 执行过程 1. Loadding :类的信息从文件中获取并且载入到JVM内存中 2. Verrifying: 检查读入的结构是否符合JVM规范的描述 3. Preparing: 分配一个结构用来存储类信息 4. Resolving: 把这个类的常量池所有的符号引用改变成直接引用 5. Initializing: 执行静态初始化程序,把静态变量初始化指定的值

    • Java 内存管理

      • Java 栈区

        用来存放Java方法执行的所有数据 ps: method call-> a -> b - c;栈区由栈帧组成,一个栈帧代表一个方法的执行。

        那什么是栈帧呢?每一个方法从调用到执行完成就对应一个栈帧在虚拟机中入栈到出栈。每一个栈帧包括局部变量表、栈操作数、动态链接、方法出口。例如(StackOverFlow异常)

        本地方法栈:和Java方法栈如出一辙,只不过本地方法栈是专门为Native方法服务的

      • 方法区

        存储被虚拟机加载的类信息,常量,静态变量,即是编译器后等数据,用于占据内存的

      • Java堆

        所有通过New创建的对象的内存都在堆中分配,是虚拟机中最大的一块内存,是GC 要回收的部分

        1. Young Generation : 刚刚New出来的对象
        2. Old Generation: 当Young Generation 中内存空间不足的时候,就会将Young Generation 中的对象按照一定的算法、规则等存放到Old Generation, 这样 Young Generation 就可以继续分配内存,当两者都没有剩余的空间的时候,就会发生OOM异常,垃圾回收器主要针对这两块内存区域,
        3. Permanent Generation: Java8 已经移除

        特点:Young Old Generation 可以动态分配,当我们的服务器处理的是及时通讯相关服务,就可以将Young Generation内存区域调整大一些;当我们不需要频繁去创建对象的时候,可以将Young Generation 内存区域调整小一些,这样达到内存对象常驻的效果

    • Java 内存回收机制

      1. 垃圾回收算法

        • 引用计数算法

          缺点:互相循坏引用 ,两个对象不可达,但是GC依然不会回收

        • 可达性算法

      2. 引用类型

        强引用、弱引用、软引用、虚引用

      3. 如何回收垃圾

        • 标记-清除算法

          优点: 内存块不需要进行对象移动,存活对象比较多的时候,高效; 缺点: 容易造成内存碎片,不利于后续对象的分配

        • 复制算法

          优点:存活的对象比较少,比较高效 缺点:成本需要一块内存作为交换空间

        • 标记-整理算法

          优点: 解决内存碎片问题 缺点: 成本较高一点

      4. 触发回收机制

        • [x] Java虚拟机无法再为新的对象分配内存空间
        • [ ] 手动调用System.gc() 强烈不推荐
        • [x] 低优先级的GC线程,被Jvm 启动了,执行GC
  2. Dalvik 与 jvm的不同

    • 执行的文件不同 一个是dex 一个是class文件
    • 类加载的系统(ClassLoader)与JVM的区别比较大
    • jvm 只能同时存在一个,DVM可以同时存在多个
    • DVM 是基于寄存器的(运行更快),JVM 是基于栈的
  3. ART比Dalvik有哪些优势

    • DVM 使用的是JIT来将字节码转换成机器码(每次运行),效率低
    • ART 是采用AOT的预编译技术(安装的时候就将字节码转换成机器码存储于介质中,不需要每次进行转换),执行速度更快
    • ART 会占用更多的应用安装时间和存储空间(以空间换时间)

class loader(Java Android)

类是如何加载到虚拟机的?

  1. Java 中的ClassLoader回顾

    具体回顾 -> java代码的编译和执行过程

  2. Android中ClassLoader 作用详解

    • Android ClassLoader的种类

      • BootsClassLoader

        用来加载Android framework层的一些dex文件

      • PathClassLoader

        用来加载已经安装到系统中的apk文件中的dex文件

      • DexClassLoader

        用来加载指定目录中dex文件

      • BaseDexClassLoader

        是PathClassLoader DexClassLoader 的父类

      一个App至少需要BootClassLoader 和PathClassLoader

    • Android ClassLoader 的特点

      • 双亲代理模型特点

        当前的classLoader去加载此类,如果当前此类已经被ClassLoader加载过就不再加载,直接返回; 如果未加载,便会查询它的Parents 是否加载过此类,如果加载过 就返回parents加载过的字节码文件; 如果整个继承线的都没有加载过此类,便会子类真正的加载,提高类加载效率。这样就会带来以下两个作用

      • 类加载的共享功能 一些FrameWork层级的类 ,一旦被顶层的classLoader加载过,那么它就会缓存到内存里面,以后任何地方用到,就不用重新加载了

      • 类加载的隔离功能 不同继承路线上的ClassLoader 加载的类不是同一个类,避免开发者自己写一代码伪造成系统的类库来访问我们系统可见成员变量。例如:系统层级的类一般初始化的时候就会加载,比如java.lang.String, 应用程序启动之前就会被系统加载,如果在一个app里面写一个自定String 替换掉java.lang.String 会造成严重的安全问题。判断是否是同一个类判断,除了className packageName 另外还需要是同一个ClassLoader加载的。

    • ClassLoader 源码 (加载流程)

      ClassLoader loadClass 首先判断被自己或者双亲加载过,如果未加载过,调用BaseDexClassLoader 的findClass,调用DexPathList findClass ,并且完成将dex文件转换成DexFile ,转换成Elements, 遍历数据,调用DexFile loadClassBinaryName - > native

  3. Android 中动态加载要点?

    • 有许多组件(Activity)类需要注册才能使用
    • 资源动态加载复杂(注册、兼容性)
    • 程序运行的时候需要一个上下文环境

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值