Java 在方法之前插入return会导致VerifyError而不显示消息

Java 在方法之前插入return会导致VerifyError而不显示消息,java,bytecode,instrumentation,javassist,javaagents,Java,Bytecode,Instrumentation,Javassist,Javaagents,我刚刚尝试更改方法的行为:替换返回值: ctMethod.insertBefore(“返回null;”); 转换工作非常完美,我甚至将clazz.toBytecode()写入一个文件,IntelliJ IDEA成功地反编译了.class文件,我可以在那里看到我的更改 但是,有一个错误阻止了类的重新转换,它似乎是在我的转换器执行后抛出的,它在本机代码中,并且没有消息: java.lang.VerifyError 位于java.instrument/sun.instrumentation.Inst

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

ctMethod.insertBefore(“返回null;”);
转换工作非常完美,我甚至将
clazz.toBytecode()
写入一个文件,IntelliJ IDEA成功地反编译了
.class
文件,我可以在那里看到我的更改

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

java.lang.VerifyError
位于java.instrument/sun.instrumentation.InstrumentationImpl.retransformClasses0(本机方法)
位于java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
在[我称之为重传类的地方]。。。
这是什么意思?我做错了什么

如果我执行
ctMethod.insertBefore(“System.out.println(1);”)相反,它开始工作


javassist的版本是
3.26.0-GA
。同样的情况也发生在
3.27.0-GA
3.27.0-GA-bugfix-328
setBody
ctMethod.setBody(“return null;”;
)解决了这个问题:现在我返回了空值。

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

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

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

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



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

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

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

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



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

字节码中可能存在无法访问的代码,但需要注意。然而,这里我们有Javassist混合了源代码概念和字节码操作,并且无法生成有效的字节码。这是这个概念的代价,允许开发人员在不理解字节码的情况下进行字节码操作。稍微限定一下“一些预防措施”是很有意思的,因为它可能值得与Javassist维护人员讨论。也许他可以改进一下工具。几个月前,当我生成一个有条件的
if(foo)返回时,他确实为我修复了一个相关的bug语句,现在可以正常工作。这里的声明是无条件的。“我不是像你这样的字节码专家,”霍尔格说。因此,请阐明一些情况,这将是有趣的。谢谢。验证器需要一个stackmap表条目来描述不可访问代码开头的堆栈帧状态。由于方法项处的状态是隐含的,因此只有
this
和每个参数的局部变量,代码生成器首先必须具体化等效堆栈帧项,然后根据插入的代码对其进行移位。Javassist必须对条件分支执行类似的操作,例如,
insertBefore(“if(Math.random()<1)System.out.println();”)
需要在语句后面输入一个条目。也许,它正确地处理了
insertBefore(“if(Math.random()<1)returnnull;”)
。@Holger的评论让我觉得您想要的应该是可能的,并且在这种情况下Javassist存在缺陷。我已经有一段时间没有使用JA了,也许我可以在有几个周期的时候研究它。更新:我认为可以在Javassist中做一些事情来解决这个问题,看看我刚才创建的是什么。字节码中可能存在无法访问的代码,但需要注意。然而,这里我们有Javassist混合了源代码概念和字节码操作,并且无法生成有效的字节码。这是这个概念的代价,允许开发人员在不理解字节码的情况下进行字节码操作。稍微限定一下“一些预防措施”是很有意思的,因为它可能值得与Javassist维护人员讨论。也许他可以改进一下工具。几个月前,当我生成一个有条件的
if(foo)返回时,他确实为我修复了一个相关的bug语句,现在可以正常工作。这里的声明是无条件的。“我不是像你这样的字节码专家,”霍尔格说。因此,请阐明一些情况,这将是有趣的。谢谢。验证器需要一个stackmap表条目来描述不可访问代码开头的堆栈帧状态。由于方法项处的状态是隐含的,因此只有
this
和每个参数的局部变量,代码生成器首先必须具体化等效堆栈帧项,然后根据插入的代码对其进行移位。Javassist必须对条件分支执行类似的操作,例如,
insertBefore(“if(Math.random()<1)System.out.println();”)
需要在语句后面输入一个条目。也许,它正确地处理了
insertBefore(“if(Math.random()<1)returnnull;”)
。@Holger的注释不是m