Javassist:
Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wsd</groupId> <artifactId>testjavassist</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--javassist 依赖--> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.29.1-GA</version> </dependency> <!--junit 依赖--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies> </project>
利用javassist 生成一个类A,创建A类的 instance a and 调用 method of a
package com.wsd; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import javassist.Modifier; import org.junit.Test; import java.lang.reflect.Method; /** * @program: webmybatis * @description: test Javassist * @author: Mr.Wang * @create: 2023-07-04 22:02 **/ public class TestJavassist { @Test public void testGenerateClass() throws Exception{ //获取一个默认的 ClassPool 实例 //Javassist 是一个 Java 字节码编辑库,它可以在运行时修改已加载的类或者生成新的类。 // ClassPool 是 Javassist 的核心组件,它是一个类容器,负责存储和管理字节码(.class 文件) ClassPool classPool = ClassPool.getDefault(); //创建一个类对象,需要告知全类名 CtClass ctClass = classPool.makeClass("com.wsd.TestGenerateCode"); // 创建方法 // 1.返回值类型 2.方法名 3.形式参数列表 4.所属类 CtMethod ctMethod = new CtMethod(CtClass.voidType, "execute", new CtClass[]{}, ctClass); // 设置方法的修饰符列表 ctMethod.setModifiers(Modifier.PUBLIC); // 设置方法体 ctMethod.setBody("{System.out.println(\"hello world\");}"); // 给类添加方法 ctClass.addMethod(ctMethod); // 生成的类加载到JVM,返回 Class Class<?> aClass = ctClass.toClass(); //反射创建 instance Object o = aClass.newInstance(); //获取对象的 execute method Method method = aClass.getDeclaredMethod("execute"); //调用 method method.invoke(o); } }
添加参数
- --add-opens java.base/java.lang=ALL-UNNAMED
- --add-opens java.base/sun.net.util=ALL-UNNAMED
run to success
VM options 是用于配置 Java 虚拟机的启动参数。这些参数可以影响 JVM 的性能、资源使用和行为
Environment variables 是用于设置操作系统环境变量的。环境变量可以在程序运行时影响程序行为
环境变量是键值对形式的数据
问题的原因:
在 Java 9 及以后的版本中,模块系统(Jigsaw)的引入为 Java 平台带来了更严格的封装。默认情况下,Java 核心库的某些包和类是不允许通过反射访问的。
VM options 设置为
--add-opens java.base/java.lang=ALL-UNNAMED
。这个参数将 java.base 模块中的 java.lang 包打开,使得所有未命名模块(即,未通过模块系统明确指定的模块)可以访问这个包中的类。这样,Javassist 就可以操作 java.lang 包中的类了。Environment variables 设置为
--add-opens java.base/sun.net.util=ALL-UNNAMED
。类似地,这个参数将 java.base 模块中的 sun.net.util 包打开,使得所有未命名模块可以访问这个包中的类。这对于 Javassist 在操作 Java 17 字节码时可能需要访问 sun.net.util 包中的一些类是必要的。这些设置确保了 Javassist 在 Java 17 环境下可以正常工作,通过打开必要的包来访问和修改 Java 字节码。