简述
Javassist(Java Programming Assistant)是一个 操作Java 字节码的类库,主要用于在运行时或编译时修改 Java 类的字节码。
它提供了相对简单的 API,让开发者可以动态地创建、修改和加载 Java 类 , 从而实现诸如动态代理、AOP(面向切面编程)、代码生成等高级功能。
API学习
1)ClassPool
作用:ClassPool 作为一个类管理器,用于动态加载、操作 (对类的字段、方法进行增删改查操作) 和生成 Java 类的字节码。        
相关API
① ClassPool.getDefault()
介绍:获取默认类池,采用单例模式,每次获取的类池都是同一个
② makeClass(String className)、
makeInterface(String className)、
makeAnnotation(String className) 等
介绍:在内存中创建类、接口、注解的字节码,返回的都是CtClass对象,此时还并未将类装载到JVM
③ get(String className) 、
getCtClass(String className)
介绍:获取内存中类的字节码对象
2)CtClass
作用:封装类的字节码信息(这里的类是统称,代表Java中的类、接口、注解等)
相关API
① void addField(CtField f)、
void addMethod(CtMethod m)、
void addConstructor(CtConstructor c)
添加字段、方法、构造器
② void addInterface(CtClass ctInterface)、
void setInterfaces(CtClass[] list)
继承一个接口、多个接口
③ void setSuperclass(CtClass clazz)
指定父类
④ Class<?> toClass()
将字节码类装载到JVM,并返回Class对象
⑤ void writeFile(String directoryName)
将类保存到文件
应用
导入maven依赖
<!--  javassist  -->
<dependency>
   <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.29.2-GA</version>
</dependency>
<!--  单元测试  -->
<dependency>
   <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>创建如下的一个接口,一个类
package com.xxx;
public interface FunctionInterface {
    void print(Object o);
}
package com.xxx;
public class FunctionImpl implements FunctionInterface{
    public void print(Object o) {
        System.out.println(o);
    }
}利用javassist生成类代码如下:
① 在内存中创建接口FunctionInterface的字节码,并加载到JVM
 Class<?> makeFunctionInterface() throws Exception {
     //  1.获取默认类池
     ClassPool classPool = ClassPool.getDefault();
     //  2.创建接口的内存字节码
     CtClass functionInterfaceCt = classPool.makeInterface("com.xxx.FunctionInterface");
     //  3.在内存中添加方法声明
     //      3.1创建方法声明,并指定所属
     CtMethod printMethodDeclare = CtMethod.make("void print(Object o);", functionInterfaceCt);
     //      3.2添加方法声明
     functionInterfaceCt.addMethod(printMethodDeclare);
     //  4.将接口装载到虚拟机
     Class<?> functionInterface = functionInterfaceCt.toClass();
     return functionInterface;
 }② 在内存中创建类FunctionImpl的字节码,并加载到JVM
Class<?> makeFunctionImpl() throws Exception {
     //  1.获取默认类池
    ClassPool classPool = ClassPool.getDefault();
    //  2.创建类的内存字节码
    CtClass functionImplCt = classPool.makeClass("com.xxx.FunctionImpl");
    //  3.继承接口
    functionImplCt.addInterface(classPool.getCtClass("com.xxx.FunctionInterface"));
    //  4.在内存中添加方法实现
    //      4.1创建方法实现,并指定所属
    CtMethod printMethodImpl = CtMethod.make("public void print(Object o){System.out.println(o);}", functionImplCt);
    //      4.2添加方法实现
    functionImplCt.addMethod(printMethodImpl);
    //  5.将类装载到虚拟机
    Class<?> functionImpl = functionImplCt.toClass();
    return functionImpl;
}③ 通过反射测试对象的生成以及print方法的调用
void testNewObject() throws Exception {
     //  1.反射创建对象
    Object functionImplObject = Class.forName("com.xxx.FunctionImpl").newInstance();
    //  2.获取print方法
    Method printMethod = functionImplObject.getClass().getMethod("print", Object.class);
    //  3.执行方法
    printMethod.invoke(functionImplObject, "hello, javassist!");
}问题解决
java.lang.reflect.InaccessibleObjectException:如果JDK版本>8,那么添加如下JVM参数和环境变量参数:
JVM参数:--add-opens java.base/java.lang=ALL-UNNAMED
环境变量:--add-opens java.base/sun.net.util=ALL-UNNAMED




















