Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类,并加载到JVM中;还可以在JVM加载时修改一个类文件。Javassist使用户不必关心字节码相关的规范也是可以编辑类文件的。

🥟javassist原理与使用 - 图1

Javassist API

描述
ClassPool ClassPool是一个存储CtClass的容器,如果调用get
方法会搜索并创建一个表示该类的CtClass对象
CtClass CtClass表示的是从ClassPool获取的类对象,可对该类就行读写编辑等操作
CtMethod 可读写的类方法对象
CtConstructor 可读写的类构造方法对象
CtField 可读写的类成员变量对象

代码示例

  1. package com.ctf.ssist;
  2. import org.apache.ibatis.javassist.*;
  3. import java.util.Arrays;
  4. public class JavaSsistTest {
  5. public static void main(String[] args) throws Exception {
  6. //创建ClassPool对象
  7. ClassPool classPool = ClassPool.getDefault();
  8. try{
  9. CtClass ctClass = classPool.get("com.ctf.ssist.Test");
  10. System.out.println("解析类名:"+ ctClass.getName()+"父类"+ ctClass.getSuperclass().getName()+", 实现接口"+ Arrays.toString(ctClass.getInterfaces()));
  11. System.out.println("================================================================");
  12. //获取所有的构造方法
  13. CtConstructor[] ctConstructor = ctClass.getDeclaredConstructors();
  14. for (CtConstructor constructor : ctConstructor) {
  15. System.out.println(constructor);
  16. }
  17. System.out.println("====================================");
  18. //获取所有的成员变量
  19. CtField[] ctFields = ctClass.getDeclaredFields();
  20. for (CtField ctField : ctFields) {
  21. System.out.println(ctField);
  22. }
  23. System.out.println("====================================");
  24. //获取所有的成员方法
  25. CtMethod[] ctMethods = ctClass.getDeclaredMethods();
  26. for (CtMethod ctMethod : ctMethods) {
  27. System.out.println(ctMethod);
  28. }
  29. System.out.println("====================================");
  30. } catch (NotFoundException e){
  31. e.printStackTrace();
  32. }
  33. }
  34. }

运行结果

🥟javassist原理与使用 - 图2

个人感觉这个类似于Java的反射

使用:动态创建Java类的二进制文件

  1. package com.ctf.ssist;
  2. import org.apache.commons.io.FileUtils;
  3. import org.apache.ibatis.javassist.ClassPool;
  4. import org.apache.ibatis.javassist.CtClass;
  5. import org.apache.ibatis.javassist.CtField;
  6. import org.apache.ibatis.javassist.CtMethod;
  7. import java.io.File;
  8. public class JavassistTestPro {
  9. public static void main(String[] args) {
  10. ClassPool classPool = ClassPool.getDefault();
  11. //使用ClassPool创建一个类
  12. CtClass ctClass = classPool.makeClass("com.ctf.ssist.JavassistHelloWorld");
  13. try{
  14. CtField ctField = CtField.make("private static String content = \"yiyandingzhen\";", ctClass);
  15. ctClass.addField(ctField);
  16. CtMethod ctMethod = CtMethod.make("public static void main(String[] args) {System.out.println(content);}", ctClass);
  17. ctClass.addMethod(ctMethod);
  18. File classFilePath = new File(new File(System.getProperty("user.dir"), "/src/main/java/com/ctf/ssist/"), "JavassistHelloWorld.class");
  19. byte[] bytes = ctClass.toBytecode();
  20. FileUtils.writeByteArrayToFile(classFilePath, bytes);
  21. }catch (Exception e){
  22. e.printStackTrace();
  23. }
  24. }
  25. }

结果

🥟javassist原理与使用 - 图3