Javassist - 从方法中删除静态修饰符
Javassist - Remove static modifier from method
我正在编写一些 Javassist 代码来拦截方法调用并将它们替换为代理。为此,我使用 ExprEditor 按以下方式替换调用:
public static void main(String[] args) {
try {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("Test");
CtMethod meth = ctClass.getDeclaredMethod("main");
meth.instrument(new ExprEditor() {
@Override
public void edit(final MethodCall m) throws CannotCompileException {
try {
if (m.getClassName().contains("Functions")) {
/* MAKE NON STATIC
CtClass old = pool.get(m.getClassName());
m.getMethod().setModifiers(Modifier.PUBLIC);
old.toClass();
*/
String s = m.getClassName() + " proxy = (" +
m.getClassName() + ") " + Main.class.getName() + ".create(" + m.getClassName() + ".class);" +
" $_ = proxy." + m.getMethodName() + "($$);";
m.replace(s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
Class clazz = ctClass.toClass();
Method method = clazz.getMethod("main", String[].class);
method.invoke(null, new Object[]{new String[]{}});
} catch (InvocationTargetException e) {
e.getCause().printStackTrace();
} catch (NoSuchMethodException | IllegalAccessException | NotFoundException | CannotCompileException e) {
e.printStackTrace();
}
}
只要方法不是静态的,它就可以正常工作。现在我试图通过使用注释代码将静态方法更改为非静态方法。
在我看来,这应该可行,并且在 Javassist 文档中对其他修饰符也有类似的用法,但是当我取消注释并 运行 它时,我收到以下错误消息:
javassist.CannotCompileException: by java.lang.ClassFormatError: Arguments can't fit into locals in class file Functions/Color
我还尝试删除静态修饰符,而不是仅仅将修饰符设置为 public
m.getMethod().setModifiers(m.getMethod().getModifiers() & ~Modifier.STATIC);
但问题依旧。
这真的可能吗?
所以您正试图从 class 测试中的保留入口点方法名称 "main" 中删除静态修饰符。我认为编译器不会让你这样做,因为 main 是一个保留的方法名称,只能有一个预定义的签名。而且,静态方法也有问题;当从 class 中调用时,如果您删除静态修饰符,对它们的所有调用也会导致编译错误,因为它们在原始代码中未被指定为实例方法。
我正在编写一些 Javassist 代码来拦截方法调用并将它们替换为代理。为此,我使用 ExprEditor 按以下方式替换调用:
public static void main(String[] args) {
try {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("Test");
CtMethod meth = ctClass.getDeclaredMethod("main");
meth.instrument(new ExprEditor() {
@Override
public void edit(final MethodCall m) throws CannotCompileException {
try {
if (m.getClassName().contains("Functions")) {
/* MAKE NON STATIC
CtClass old = pool.get(m.getClassName());
m.getMethod().setModifiers(Modifier.PUBLIC);
old.toClass();
*/
String s = m.getClassName() + " proxy = (" +
m.getClassName() + ") " + Main.class.getName() + ".create(" + m.getClassName() + ".class);" +
" $_ = proxy." + m.getMethodName() + "($$);";
m.replace(s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
Class clazz = ctClass.toClass();
Method method = clazz.getMethod("main", String[].class);
method.invoke(null, new Object[]{new String[]{}});
} catch (InvocationTargetException e) {
e.getCause().printStackTrace();
} catch (NoSuchMethodException | IllegalAccessException | NotFoundException | CannotCompileException e) {
e.printStackTrace();
}
}
只要方法不是静态的,它就可以正常工作。现在我试图通过使用注释代码将静态方法更改为非静态方法。 在我看来,这应该可行,并且在 Javassist 文档中对其他修饰符也有类似的用法,但是当我取消注释并 运行 它时,我收到以下错误消息:
javassist.CannotCompileException: by java.lang.ClassFormatError: Arguments can't fit into locals in class file Functions/Color
我还尝试删除静态修饰符,而不是仅仅将修饰符设置为 public
m.getMethod().setModifiers(m.getMethod().getModifiers() & ~Modifier.STATIC);
但问题依旧。
这真的可能吗?
所以您正试图从 class 测试中的保留入口点方法名称 "main" 中删除静态修饰符。我认为编译器不会让你这样做,因为 main 是一个保留的方法名称,只能有一个预定义的签名。而且,静态方法也有问题;当从 class 中调用时,如果您删除静态修饰符,对它们的所有调用也会导致编译错误,因为它们在原始代码中未被指定为实例方法。