【问题标题】:Inserting return before method causes VerifyError without message在方法之前插入 return 会导致没有消息的 VerifyError
【发布时间】:2020-10-27 19:15:14
【问题描述】:

我刚刚尝试改变一个方法的行为:替换返回值:

ctMethod.insertBefore("return null;");

转换效果很好,我什至将clazz.toBytecode() 写入文件,IntelliJ IDEA 成功反编译了.class 文件,我可以在那里看到我的更改。

但是,有一个错误阻止了类的重新转换,它似乎是在我的转换器执行后抛出的,它在本机代码中,并且没有消息:

java.lang.VerifyError
    at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
    at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
    at [place where I call retransformClasses]...

这是什么意思?我做错了什么?

如果我改为使用ctMethod.insertBefore("System.out.println(1);");,它就会开始工作。

javassist 的版本是3.26.0-GA3.27.0-GA3.27.0-GA-bugfix-328 上也会发生同样的情况。

【问题讨论】:

    标签: java bytecode instrumentation javassist javaagents


    【解决方案1】:

    您自己的回答提到了另一种方法,但没有回答您的问题:

    这是什么意思?我做错了什么?

    在问题的开头添加无条件的return 语句会使该方法的其余部分无法访问代码。如果在任何 Java 类中添加这样的语句,编译将失败并出现 "unreachable statement" 错误。可能字节码验证器也执行这样的检查。


    更新:经过一些讨论和自己的研究,我认为可以在 Javassist 中做一些事情来解决这个问题,请参阅我刚刚创建的 issue #352

    【讨论】:

    • 在字节码中可能存在无法访问的代码,但要采取一些预防措施。然而,在这里我们让 Javassist 将源代码概念与字节码操作混合在一起,并且无法生成有效的字节码。这就是概念的代价,允许开发人员在不了解字节码的情况下进行字节码操作。
    • 稍微限定“一些预防措施”会很有趣,因为它可能值得与 Javassist 维护者讨论。也许他可以在那里改进一下工具。几个月前,当我在构造函数的开头生成条件if (foo) return; 语句时,他确实为我修复了一个相关的错误,现在可以正常工作了。这里的声明是无条件的。 @Holger,我不是像你这样的字节码专家。所以请说明一下情况,那会很有趣。谢谢。
    • 验证者需要一个 stackmap 表条目来描述不可访问代码开头的堆栈帧状态。由于方法入口的状态是隐含的,只有this 和每个参数的局部变量,代码生成器首先必须实现一个等效的堆栈帧入口,然后通过插入的代码移动它。 Javassist 必须对条件分支做类似的事情,例如insertBefore("if(Math.random() < 1) System.out.println();") 在语句后需要一个条目。也许,它正确处理了insertBefore("if(Math.random() < 1) return null;")
    • @Holger 的 cmets 让我认为您想要的应该是可能的,并且在这种情况下存在 Javassist 的缺点。好久没用JA了,也许有几个周期可以看看。
    • 更新:我认为可以在 Javassist 中做一些事情来解决这个问题,请参阅我刚刚创建的 issue #352
    【解决方案2】:

    setBody (ctMethod.setBody("return null;");) 解决了问题:现在我返回了空值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 2021-02-25
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      相关资源
      最近更新 更多