Java字节增强码技术

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 编码的形式,而不需要了解虚拟机指令,就能动态改 变类的结构或者动态生成类
      • 四个重要的类
        • ClassPool
          • 从开发视角来看,ClassPool是一张保存CtClass信息的 HashTable,key 为类名,value为类名对应的CtClass对象。
          • 当需要对某个类进行修改时,就是通过pool.getCtClass(“className”) 方法从pool中获取到相应的CtClass。
        • CtClass(compile-time class)
          • 编译时类信息,它是一个class文件在代码中的抽象表现形式,可以通过一个类的全限定名来获取一个CtClass对象, 用来表示这个类文件。
        • CtMethod
          • 对应的是类中的方法
        • CtField
          • 对应的是类中的属性
  • 运行时类的重载
    • Instrument
      • 依赖JVMTI的Attach API机制实现。
      • JDK 1.6 之后,instrument支持了在运行时对类定义的修改。使用instrument的类修改功能,需要实现它提供的ClassFileT-ransformer接口,定义一个类文件转换器。
      • 使用场景
        • 热部署: 不部署服务而对线上服务做修改,可以做打点、增加日志等操作。
        • Mock: 测试时候对某些服务做 Mock。
        • 性能诊断工具: 比如 bTrace 就是利用 Instrument,实现无侵入地跟踪一个正在运行的JVM,监控到类和方法级别的状态信息。
      • 工具
        • bTrace
        • JVM-SANDBOX
        • Arthas
  • Arthas
  • btrace
    • BTrace 主要有下面几个模块:
      • BTrace脚本: 利用BTrace定义的注解,我们可以很方便地根据需要进行脚本的开发。
      • Compiler: 将 BTrace 脚本编译成 BTrace class 文件。
      • Client: 将 class文件发送到 Agent。
  1. Agent: 基于 Java 的 Attach Api,
  2. Agent可以动态附着到一个运行的JVM上,
  3. 然后开启一个 BTrace Server,接收 client 发过来的BTrace脚本;
  4. 解析脚本
  5. 然后根据脚本中的规则找到修改的类;
  6. 修改字节码后,调用 Java Instrument 的 reTransform 接口,完成对对象行为的修改并使之生效。
  • BTrace 脚本的限制
  • 不允许创建对象
  • 不允许创建数组
  • 不允许抛异常
  • 不允许 catch 异常
  • 不允许随意调用其他对象或者类的方法,只允许调用 com.sun.btrace.BTraceUtils 中提供的静态方法(一些数据处理和信息输出工具)
  • 不允许改变类的属性
  • 不允许有成员变量和方法,只允许存在 static public void 方法
  • 不允许有内部类、嵌套类
  • 不允许有同步方法和同步块
  • 不允许有循环
  • 不允许随意继承其他类(当然,java.lang.Object 除外)
  • 不允许实现接口
  • 不允许使用 assert
  • 不允许使用 Class 对象
  • 实现了一种在不重启、不侵入目标JVM应用的AOP解决方案。
  • JVM-SANDBOX属于基于Instrumentation的动态编织类的AOP框架,通过精心构造了字节码增强逻辑,使得沙箱的模块能在不违反JDK约束情况下实现对目标应用方法的无侵入运行时AOP拦截
  • 沙箱的特性
    • 无侵入:目标应用无需重启也无需感知沙箱的存在
    • 类隔离:沙箱以及沙箱的模块不会和目标应用的类相互干扰
    • 可插拔:沙箱以及沙箱的模块可以随时加载和卸载,不会在目标应用留下痕迹
    • 多租户:目标应用可以同时挂载不同租户下的沙箱并独立控制
    • 高兼容:支持JDK[6,11]
  • 沙箱常见应用场景
    • 线上故障定位
    • 线上系统流控
    • 线上故障模拟
    • 方法请求录制和结果回放
    • 动态日志打印
    • 安全信息监测和脱敏
  • 核心原理
    • 事件驱动,基于BEFORE、RETURN和THROWS三个环节事件分离,沙箱的模块可以完成很多类AOP的操作。
      • 可以感知和改变方法调用的入参
      • 可以感知和改变方法调用返回值和抛出的异常
      • 可以改变方法执行的流程
        • 在方法体执行之前直接返回自定义结果对象,原有方法代码将不会被执行
        • 在方法体返回之前重新构造新的结果对象,甚至可以改变为抛出异常
        • 在方法体抛出异常之后重新抛出新的异常,甚至可以改变为正常返回
    • 类隔离策略
      • 沙箱通过自定义的SandboxClassLoader破坏了双亲委派的约定,实现了和目标应用的类隔离。所以不用担心加载沙箱会引起应用的类污染、冲突。各模块之间类通过ModuleJarClassLoader实现了各自的独立,达到模块之间、模块和沙箱之间、模块和应用之间互不干扰。

      • 类增强策略
        • 沙箱通过在BootstrapClassLoader中埋藏的Spy类完成目标类和沙箱内核的通讯

      • 整体架构

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值