如何使用Javassist移除方法static修饰符并实现方法调用代理拦截?
嘿,我来帮你搞定这两个Javassist的需求!咱们拆成两部分来一步步实现:
1. 完善方法调用拦截与代理替换
你用ExprEditor拦截方法调用的思路完全没问题,接下来只需要补全判断逻辑,再通过replace()方法把原调用替换成代理逻辑就行。这里给你一个完整的可运行示例,假设你要拦截类名包含Function的方法调用,替换成自定义代理类的调用:
import javassist.*; import javassist.expr.ExprEditor; import javassist.expr.MethodCall; public class JavassistInterceptor { public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); // 获取要修改的目标类 CtClass ctClass = pool.get("Test"); // 获取目标类中要植入拦截逻辑的方法(这里是Test的main方法) CtMethod targetMethod = ctClass.getDeclaredMethod("main"); // 用ExprEditor遍历方法内的所有方法调用 targetMethod.instrument(new ExprEditor() { @Override public void edit(MethodCall m) throws CannotCompileException { // 匹配你要拦截的目标方法 if (m.getClassName().contains("Function") && m.getMethodName().equals("doSomething")) { // 替换原方法调用为代理方法调用 // $_ 代表原方法的返回值,$$ 代表原方法的所有参数(按顺序传递) m.replace("{ $_ = com.yourpackage.ProxyHandler.invokeProxy($$); }"); } } }); // 生成修改后的类文件(可选择写入磁盘或直接加载到JVM) ctClass.writeFile("./output"); // 如果要直接加载到当前JVM:ctClass.toClass(); } }
关键细节提醒:
$_必须赋值,否则原方法的返回值会丢失,导致逻辑异常- 如果你需要单独处理某个参数,可以用
$1、$2这样的占位符分别指代第1、第2个参数 - 要保证代理方法的参数列表和原方法匹配,或者在代理类中做参数适配处理
2. 移除方法的static修饰符
要移除方法的static修饰符,借助CtMethod的setModifiers()方法结合java.lang.reflect.Modifier工具类就能轻松实现:
// 接上面的代码,假设要移除Test类中名为staticFunc的静态方法修饰符 CtMethod staticMethod = ctClass.getDeclaredMethod("staticFunc"); // 获取原方法的修饰符,通过位运算移除static标记 int updatedModifiers = staticMethod.getModifiers() & ~Modifier.STATIC; staticMethod.setModifiers(updatedModifiers); // 别忘了重新生成修改后的类 ctClass.writeFile("./output");
注意:如果移除的是main方法的static修饰符,这个类就无法再通过java Test的方式启动了——因为JVM要求main方法必须是public static void类型,这一点要根据你的实际需求权衡。
内容的提问来源于stack exchange,提问作者ggfpc
相关产品推荐
相关产品推荐

