简单介绍下几种java字节码增强技术。

ASM

ASM是一个Java字节码操控框架,它能被用来动态生成类或者增强既有类的功能。ASM可以直接产生class文件,也可以在类被加载入Java虚拟机之前动态改变类行为。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。

主页:https://asm.ow2.io/index.html

ASM框架中的核心类有以下几个:

  ①  ClassReader:该类用来解析编译过的class字节码文件。

  ②  ClassWriter:该类用来重新构建编译后的类,比如说修改类名、属性以及方法,甚至可以生成新的类的字节码文件。

  ③  ClassAdapter:该类也实现了ClassVisitor接口,它将对它的方法调用委托给另一个ClassVisitor对象。

参考代码:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes; public class GeneratorClass { public static void main(String[] args) throws IOException {
//生成一个类只需要ClassWriter组件即可
ClassWriter cw = new ClassWriter(0);
//通过visit方法确定类的头部信息
cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT+Opcodes.ACC_INTERFACE,
"com/asm3/Comparable", null, "java/lang/Object", new String[]{"com/asm3/Mesurable"});
//定义类的属性
cw.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,
"LESS", "I", null, new Integer(-1)).visitEnd();
cw.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,
"EQUAL", "I", null, new Integer(0)).visitEnd();
cw.visitField(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_STATIC,
"GREATER", "I", null, new Integer(1)).visitEnd();
//定义类的方法
cw.visitMethod(Opcodes.ACC_PUBLIC+Opcodes.ACC_ABSTRACT, "compareTo",
"(Ljava/lang/Object;)I", null, null).visitEnd();
cw.visitEnd(); //使cw类已经完成
//将cw转换成字节数组写到文件里面去
byte[] data = cw.toByteArray();
File file = new File("D://Comparable.class");
FileOutputStream fout = new FileOutputStream(file);
fout.write(data);
fout.close();
}
}

Javassist

Javassist是一个开源的分析、编辑和创建Java字节码的类库。

它已加入了开放源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。

主页:http://www.javassist.org/

参考代码:

import javassist.*;

public class CreatePerson {

    public static void createPseson() throws Exception {
ClassPool pool = ClassPool.getDefault(); // 1. 创建一个空类
CtClass cc = pool.makeClass("com.test.javassist.Person"); // 2. 新增一个字段 private String name;
// 字段名为name
CtField param = new CtField(pool.get("java.lang.String"), "name", cc);
// 访问级别是 private
param.setModifiers(Modifier.PRIVATE);
// 初始值是 "xiaoming"
cc.addField(param, CtField.Initializer.constant("xiaoming")); // 3. 生成 getter、setter 方法
cc.addMethod(CtNewMethod.setter("setName", param));
cc.addMethod(CtNewMethod.getter("getName", param)); // 4. 添加无参的构造函数
CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);
cons.setBody("{name = \"xiaohong\";}");
cc.addConstructor(cons); // 5. 添加有参的构造函数
cons = new CtConstructor(new CtClass[]{pool.get("java.lang.String")}, cc);
// $0=this / $1,$2,$3... 代表方法参数
cons.setBody("{$0.name = $1;}");
cc.addConstructor(cons); // 6. 创建一个名为printName方法,无参数,无返回值,输出name值
CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, cc);
ctMethod.setModifiers(Modifier.PUBLIC);
ctMethod.setBody("{System.out.println(name);}");
cc.addMethod(ctMethod); //这里会将这个创建的类对象编译为.class文件
cc.writeFile("/Users/yangyue/workspace/springboot-learn/java-agent/src/main/java/");
} public static void main(String[] args) {
try {
createPseson();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Byte Buddy

Byte Buddy是一个代码生成和操作库,用于在Java应用程序运行时创建和修改Java类,而无需编译器的帮助。
除了Java类库附带的代码生成实用程序外,Byte Buddy还允许创建任意类,并且不限于实现用于创建运行时代理的接口。
此外,Byte Buddy提供了一种方便的API,可以使用Java代理或在构建过程中手动更改类。

主页:https://bytebuddy.net/#/

参考代码:

Class<?> dynamicType = new ByteBuddy()
.subclass(Object.class)
.method(ElementMatchers.named("toString"))
.intercept(FixedValue.value("Hello World!"))
.make()
.load(getClass().getClassLoader())
.getLoaded(); assertThat(dynamicType.newInstance().toString(), is("Hello World!"));

JVM-SANDBOX

JVM沙箱容器,一种JVM的非侵入式运行期AOP解决方案:

  1. 动态增强类你所指定的类,获取你想要的参数和行信息甚至改变方法执行。
  2. 动态可插拔容器框架。

主页:https://github.com/alibaba/jvm-sandbox

参考:

https://www.jianshu.com/p/b72f66da679f

https://tech.meituan.com/2019/09/05/java-bytecode-enhancement.html

最新文章

  1. GCC学习(1)之MinGW使用
  2. 快速Android开发系列网络篇之Volley
  3. Xcode 8 支持 iOS 7 真机解决过程记录
  4. uva1262
  5. 异步编程 In .NET(转)
  6. 2016 Sichuan Province Programming Contest
  7. Word 使用技巧
  8. bzoj2298
  9. 数据库ACID、隔离级别与MVCC
  10. python面对对象编程----2:__init__
  11. 我的Python成长之路---第一天---Python基础(作业2:三级菜单)---2015年12月26日(雾霾)
  12. mysql寻呼最快
  13. 微信小程序开发带来的思考
  14. Where T:Class,new()的使用
  15. 发现大量的TIME_WAIT解决办法 -- 修改内核参数
  16. chorme调试Paused in debugger问题解决
  17. Nginx自定义404页面并返回404状态码
  18. Vuejs核心思想学习笔记
  19. SpringBoot war包部署到Tomcat服务器
  20. 【性能测试工具ab】ab工具使用

热门文章

  1. Kubernetes 实战——配置应用(ConfigMap、Secret)
  2. 从菜鸟到大神:Java高并发核心编程(连载视频)
  3. Java源码详解系列(十二)--Eureka的使用和源码
  4. Hive和Spark分区策略
  5. Pytest学习笔记7-skip和skipif的使用
  6. JavaScript实现的7种排序算法
  7. 乘风破浪,Java遇见OpenJDK GA(Build By Microsoft),即将晋升为Azure云管理服务默认JVM
  8. 图解协程调度模型-GMP模型
  9. 重新整理 .net core 实践篇————配置中心[四十三]
  10. php加密压缩文件