从Java字节码中删除指令

时间:2012-02-10 12:50:43

标签: java bytecode javassist

我一直在使用Javassist来动态操作类。虽然使用Javassist向代码添加代码相对容易,但我无法找到删除代码的方法。

此时我正在使用 nop 指令来模拟删除代码,以替换目标操作码和任何参数。但是,我认为这主要是一个黑客攻击:

  • 由于参数的字节长度不同,因此必须单独处理每个操作码。在某些情况下,我还需要在 nop pop 之间进行选择,具体取决于删除的操作码是否影响堆栈。这种操作开始变得乏味 - 并且执行它的代码变得相当复杂。所以,当然,我希望有一个现有的解决方案。

  • 最终结果用 nop 指令填充。虽然JVM应该优化那些没有性能影响,但结果字节码仍然非常不优雅,并且应该比它更大。这更像是一个美学问题,但仍有待考虑。

不幸的是,仅仅移动字节码数组的部分以填补空白是不够的 - 任何对移动代码的引用(例如分支指令索引)也应该更新。

是否可以使用Javassist删除指令?或者,是否有一个字节码操作库,可以让我轻松地做到这一点,而不必自己解析字节码?

2 个答案:

答案 0 :(得分:3)

Apache BCEL允许您delete instructions

  

删除指令也非常简单;所有指令句柄和给定范围内包含的指令都从指令列表中删除并处理。但是,当指令编程器仍然引用其中一条已删除的指令时,delete()方法可能会抛出TargetLostException。用户被迫在try-catch子句中处理此类异常,并将这些引用重定向到其他位置。

您也可以在手册中找到一个示例。

答案 1 :(得分:0)

来自javassist教程:

Javassist不允许删除方法或字段,但允许更改名称。因此,如果不再需要某个方法,则应通过调用CtMethod中声明的setName()和setModifiers()将其重命名并更改为私有方法。