我一直在使用Javassist来动态操作类。虽然使用Javassist向代码添加代码相对容易,但我无法找到删除代码的方法。
此时我正在使用 nop 指令来模拟删除代码,以替换目标操作码和任何参数。但是,我认为这主要是一个黑客攻击:
由于参数的字节长度不同,因此必须单独处理每个操作码。在某些情况下,我还需要在 nop 和 pop 之间进行选择,具体取决于删除的操作码是否影响堆栈。这种操作开始变得乏味 - 并且执行它的代码变得相当复杂。所以,当然,我希望有一个现有的解决方案。
最终结果用 nop 指令填充。虽然JVM应该优化那些没有性能影响,但结果字节码仍然非常不优雅,并且应该比它更大。这更像是一个美学问题,但仍有待考虑。
不幸的是,仅仅移动字节码数组的部分以填补空白是不够的 - 任何对移动代码的引用(例如分支指令索引)也应该更新。
是否可以使用Javassist删除指令?或者,是否有一个字节码操作库,可以让我轻松地做到这一点,而不必自己解析字节码?
答案 0 :(得分:3)
Apache BCEL允许您delete instructions:
删除指令也非常简单;所有指令句柄和给定范围内包含的指令都从指令列表中删除并处理。但是,当指令编程器仍然引用其中一条已删除的指令时,delete()方法可能会抛出TargetLostException。用户被迫在try-catch子句中处理此类异常,并将这些引用重定向到其他位置。
您也可以在手册中找到一个示例。
答案 1 :(得分:0)
来自javassist教程:
Javassist不允许删除方法或字段,但允许更改名称。因此,如果不再需要某个方法,则应通过调用CtMethod中声明的setName()和setModifiers()将其重命名并更改为私有方法。