Java字节增强码技术
- JAVA字节码增强 (类加载前强化)
- ASM
- 利用 MyClassVisitor 对已编译好的 class 文件进行修改
- ASM原理
- 对于需要手动操纵字节码的需求,可以使用ASM,它可以直接生产 .class字节码文件,也可以在类被加载入JVM之前动态修改类行为。
- ASM API
- 核心API
- ASM Core API 可以类比解析XML文件中的SAX方式,不需要把这个类的整个结构读取进来,就可以用流式的方法来处理字节码文件。非常节约内存,但是编程难度较大。
- 关键类
- ClassReader: 用于读取已经编译好的.class 文件。
- ClassWriter: 用于重新构建编译后的类,如修改类名、属性以及方法,也可以生成新的类的字节码文件。
- 各种Visitor类,CoreAPI根据字节码从上到下依次处理,对于字节码文件中不同的区域有不同的Visitor,
- 比如用于访问方法的 MethodVisi-tor、用于访问类变量的 FieldVisitor、用于访问注解的AnnotationVisitor等。
- 为了实现 AOP,重点要使用的是 MethodVisitor。
- 树形API
- ASM Tree API 可以类比解析XML文件中的DOM方式,把整个类的结构读取到内存中,缺点是消耗内存多,但是编程比较简单。
- 应用场景
- AOP(Cglib 就是基于 ASM)、热部署、修改其他jar包中的类等。
- Javassist
- 特点
- 强调源代码层次操作字节码的框架 Javassist
- 可以无须关注字节码刻板的结构,其优点就 在于编程简单。
- 直接使用 java 编码的形式,而不需要了解虚拟机指令,就能动态改 变类的结构或者动态生成类
- 四个重要的类
- 特点
- ASM
- 运行时类的重载
- Instrument
- 依赖JVMTI的Attach API机制实现。
- JDK 1.6 之后,instrument支持了在运行时对类定义的修改。使用instrument的类修改功能,需要实现它提供的ClassFileT-ransformer接口,定义一个类文件转换器。
- 使用场景
- 热部署: 不部署服务而对线上服务做修改,可以做打点、增加日志等操作。
- Mock: 测试时候对某些服务做 Mock。
- 性能诊断工具: 比如 bTrace 就是利用 Instrument,实现无侵入地跟踪一个正在运行的JVM,监控到类和方法级别的状态信息。
- 工具
- bTrace
- JVM-SANDBOX
- Arthas
- Instrument
- Arthas
- btrace
- BTrace 主要有下面几个模块:
- BTrace脚本: 利用BTrace定义的注解,我们可以很方便地根据需要进行脚本的开发。
- Compiler: 将 BTrace 脚本编译成 BTrace class 文件。
- Client: 将 class文件发送到 Agent。
- BTrace 主要有下面几个模块:
- Agent: 基于 Java 的 Attach Api,
- Agent可以动态附着到一个运行的JVM上,
- 然后开启一个 BTrace Server,接收 client 发过来的BTrace脚本;
- 解析脚本,
- 然后根据脚本中的规则找到修改的类;
- 修改字节码后,调用 Java Instrument 的 reTransform 接口,完成对对象行为的修改并使之生效。
- BTrace 脚本的限制
- 不允许创建对象
- 不允许创建数组
- 不允许抛异常
- 不允许 catch 异常
- 不允许随意调用其他对象或者类的方法,只允许调用 com.sun.btrace.BTraceUtils 中提供的静态方法(一些数据处理和信息输出工具)
- 不允许改变类的属性
- 不允许有成员变量和方法,只允许存在 static public void 方法
- 不允许有内部类、嵌套类
- 不允许有同步方法和同步块
- 不允许有循环
- 不允许随意继承其他类(当然,java.lang.Object 除外)
- 不允许实现接口
- 不允许使用 assert
- 不允许使用 Class 对象
- JVM-SANDBOX(沙箱)
- 实现了一种在不重启、不侵入目标JVM应用的AOP解决方案。
- JVM-SANDBOX属于基于Instrumentation的动态编织类的AOP框架,通过精心构造了字节码增强逻辑,使得沙箱的模块能在不违反JDK约束情况下实现对目标应用方法的无侵入运行时AOP拦截
- 沙箱的特性
- 无侵入:目标应用无需重启也无需感知沙箱的存在
- 类隔离:沙箱以及沙箱的模块不会和目标应用的类相互干扰
- 可插拔:沙箱以及沙箱的模块可以随时加载和卸载,不会在目标应用留下痕迹
- 多租户:目标应用可以同时挂载不同租户下的沙箱并独立控制
- 高兼容:支持JDK[6,11]
- 沙箱常见应用场景
- 线上故障定位
- 线上系统流控
- 线上故障模拟
- 方法请求录制和结果回放
- 动态日志打印
- 安全信息监测和脱敏
- 核心原理
- 事件驱动,基于BEFORE、RETURN和THROWS三个环节事件分离,沙箱的模块可以完成很多类AOP的操作。
- 类隔离策略
- 沙箱通过自定义的SandboxClassLoader破坏了双亲委派的约定,实现了和目标应用的类隔离。所以不用担心加载沙箱会引起应用的类污染、冲突。各模块之间类通过ModuleJarClassLoader实现了各自的独立,达到模块之间、模块和沙箱之间、模块和应用之间互不干扰。
-
-
- 类增强策略
- 沙箱通过在BootstrapClassLoader中埋藏的Spy类完成目标类和沙箱内核的通讯
- 类增强策略
-
-
-
- 整体架构
-