引言
在软件开发过程中,测试是非常重要的一个环节。而在测试过程中,自动化测试又是非常重要的一部分。随着 DevOps 的流行,自动化测试已经成为了一个必不可少的工具。而 Jenkins 作为一个开源的持续集成工具,可以非常方便地实现自动化测试。而 Monkey 则是一个 Java 平台下的测试工具,可以用来执行一些随机的、压力测试等。如果现在这个 topic 就是 hotfix ,那从广度上我觉得它应该至少包含以下系列:
- hook
- 动态加载,插件化
- 字节码插桩
- 编译(dex 分包,proguard 混淆等)
今天就来说下 hook
keyword
关于 hook 的关键字,非下面几个莫属:
- Reflection
- AOP
- Proxy
Reflection
不细说了,网上资料一大把,概括如下:
- java 程序经过 javac,编译为.class 字节码文件,这是一种连续的,紧密型的二进制字节码,它存储于磁盘上
- 然后 Java VM(代指各种虚拟机),按照自己的规范和顺序将 1 中的字节码读取到内存中的各个位置并划分区域,这个过程,就称为 class loading
- 反射,关键是靠类加载器(ClassLoader),而类加载器的职责,是在运行时根据一个指定的类的名称,找到或者生成其对应的字节码,然后从这些字节码中定义出一个 java 类,即 java.lang.Class 的一个实例
- 拿到这个 Class 后,我们可以用它来构造一个对象,也可以获取所有它里面定义的变量,方法,按照需要 get/set
AOP(Aspect Oriented Programming)
AOP,就跟 OOP(Object Oriented Programming,面向对象)一样,它俩都是一种 编程思想,但是面向对象目的模块化,封装,即一个对象完成设计出来,是为了完成它分内的事,但如果各个 module 都只做自己的事,突然有一个类似性能监控的需求下来,它要作用于所有的模块,怎么办?
就像上图,logging 应该是所有模块都要兼备的功能。可能有人会说,可以把 logging 设计为一个 interface,现有的所有 module 实现该 interface 就好了。那如果之前系统已经有一千个 module 怎么办?难道要手动去改一千个类?又或者之后系统需要扩展,再加两千个类,每次新写一个类都得实现这个 interface?
这个 logging,又或者具有 logging 属性的其他类似 module,它就是一个 aspect,需要贯穿所有目标 module,在不考虑现在量级和以后扩展量级的基础上怎么实现?这大概就是 AOP 想要描述的事情,也是它和 OOP 的区别所在,AOP 分下面两种
- 运行时 AOP:主要是动态的修改某些方法的行为,比较有名的 AOP 框架有 Xposed 和 Dexposed
- 编译时 AOP:主要是打包过程中动态修改 .class 字节码,也可以理解为字节码 hook
Proxy
Proxy(代理),这个不用说了,大家都很熟悉了,代理就相当于站在原始 client 和原始 server 之间的一个中间人,原始的输入和输出全部都经过它,它可以帮助原 client 处理事情,那么它有以下这些特点:
- 从输入到输出,精确的控制流程
- 基于第 1 点,可以理解为对原有功能的增强实现
- 静态代理:用一个明确的代理类实现
- 动态代理:在运行时生成的代理实例
这里的静态和动态指的是代理 instance 的生成时机,和『透明代理,反向代理&#x