11

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

这时候我正在模拟代码的移除,通过使用nop指令替换目标操作码和任何参数。但是,我认为这主要是一个 hack:

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

  • 最终结果是用nop指令填充的。虽然 JVM 应该在不影响性能的情况下优化这些字节码,但生成的字节码仍然非常不优雅并且比它应该的更大。这更多的是美学问题,但仍然需要考虑。

不幸的是,仅仅移动字节码数组的一部分来缩小差距是不够的——任何对移动代码的引用(例如分支指令索引)也应该更新。

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

4

2 回答 2

3

Apache BCEL允许您删除指令

指令的删除也很直接;给定范围内的所有指令句柄和包含的指令都从指令列表中删除并处置。但是,当指令目标器仍在引用已删除指令之一时,delete() 方法可能会引发 TargetLostException。用户被迫在 try-catch 子句中处理此类异常,并将这些引用重定向到其他地方。

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

于 2012-02-10T13:50:12.820 回答
0

来自 javassist 教程:

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

于 2012-02-13T03:23:28.490 回答