本篇文章将和大家分享一下关于Java字节码编程中一个非常之好用的技术javassist,下面将详细为大家介绍一下javassist技术,以及具体实例代码讲解。
一、Javassist入门
(一)Javassist是什么
Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类,并加载到JVM中;还可以在JVM加载时修改一个类文件。Javassist使用户不必关心字节码相关的规范也是可以编辑类文件的。
(二)Javassist核心API
在Javassist中每个需要编辑的class都对应一个CtCLass实例,CtClass的含义是编译时的类(compile time class),这些类会存储在Class Pool中(Class poll是一个存储CtClass对象的容器)。
CtClass中的CtField和CtMethod分别对应Java中的字段和方法。通过CtClass对象即可对类新增字段和修改方法等操作了。
(三)简单示例
为了减少演示的复杂度,示例以及之后的操作,都在Maven项目下进行,因为我们可以直接引入依赖就可以达到我们导包的目的,很方便,不用再去下载jar包,然后自己手动导入了。
1、创建一个maven项目
如果你使用的是IDEA,可以像我一样;如果是其他工具,可以自行百度,或者按照自己的经验来创建即可。
2、创建一个测试类,代码如下:
package com.ssdmbbl.javassist;
import javassist.*;
import java.io.IOException;
/**
* @author zhenghui
* @description: Javassist使用演示测试
* @date 2021/4/6 6:38 下午
*/
public class JavassistTest {
public static void main(String[] args) throws CannotCompileException, IOException {
ClassPool cp = ClassPool.getDefault();
CtClass ctClass = cp.makeClass("com.ssdmbbl.javassist.Hello");
ctClass.writeFile("./");
}
}
当运行这个代码的时候,可以看到已经在项目的根目录下创建了一个“com.ssdmbbl.javassist”包,在这个包下创建了“Hello.java”的java文件。
内容如下:
package com.ssdmbbl.javassist;
public class Hello {
public Hello() {
}
}
二、Javassist操作字节码示例
回想一下,咱们如果对一个Java正常操作的话,大概存在哪些操作呢?
- 1、咱们会对一个类添加字段;
- 2、咱们会对一个类添加方法;
好像没其他的了吧。其余的就是在方法里写代码了呗。
(一)新增一个方法
咱们继续套用上面简单示例的代码,在此基础之上进行新增一个方法。
新增方法的名字为"hello1",传递两个参数分别为int和double类型,并且没有返回值。
package com.ssdmbbl.javassist;
import javassist.*;
import java.io.IOException;
import java.net.URL;
/**
* @author zhenghui
* @description: Javassist使用演示测试
* @date 2021/4/6 6:38 下午
*/
public class JavassistTest2 {
public static void main(String[] args) throws CannotCompileException, IOException {
//找到本文件的路径,与之保存在一起
URL resource = JavassistTest2.class.getClassLoader().getResource("");
String file = resource.getFile();
System.out.println("文件存储路径:"+file);
ClassPool cp = ClassPool.getDefault();
CtClass ctClass = cp.makeClass("com.ssdmbbl.javassist.Hello");
//创建一个类名为"hello",传递参数的顺序为(int,double),没有返回值的类
/*
CtMethod(...)源代码:
public CtMethod(CtClass returnType,//这个方法的返回值类型,
String mname, //(method name)方法的名字是什么
CtClass[] parameters, //方法传入的参数类型是什么
CtClass declaring //添加到哪个类中
) {....}
*/
CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);
//设置hello方法的权限为public
ctMethod.setModifiers(Modifier.PUBLIC);
//向ctClass中添加这个方法
ctClass.addMethod(ctMethod);
//写入本地
ctClass.writeFile(file);
}
}
执行后,就可以查看生成的代码了:
可以看到,我们并没有指定参数的名字,也会给生成var1、var2依次类推