为什么Groovy AST转换在方法末尾插入null?

为什么Groovy AST转换在方法末尾插入null?,groovy,metaprogramming,abstract-syntax-tree,Groovy,Metaprogramming,Abstract Syntax Tree,我编写了一个AST转换,它为JPA映射属性创建一个setter(它既设置本地字段,又在关系的另一端调用setOwner): 这是可行的,但生成的方法最后有一个奇怪的null语句,由JD-GUI反汇编(除了一个奇数的局部变量): 这似乎不会影响实际的正确性,但这很奇怪,而且似乎是一个bug。在MethodCallExpression中,我找到了这个注释,但不知道它是否相关,因为我的方法实际上是无效的(我在上面显式地设置了它,并且没有区别): 有没有办法防止生成的方法出现虚假的null?我没有看过J

我编写了一个AST转换,它为JPA映射属性创建一个setter(它既设置本地字段,又在关系的另一端调用
setOwner
):

这是可行的,但生成的方法最后有一个奇怪的
null
语句,由JD-GUI反汇编(除了一个奇数的局部变量):

这似乎不会影响实际的正确性,但这很奇怪,而且似乎是一个bug。在
MethodCallExpression
中,我找到了这个注释,但不知道它是否相关,因为我的方法实际上是无效的(我在上面显式地设置了它,并且没有区别):


有没有办法防止生成的方法出现虚假的
null

我没有看过JD-GUI,所以我无法判断这个工具在理解字节码方面的能力,字节码不是来自Java。但一般来说,反汇编程序只能在某种程度上显示Java代码在这种情况下可能是什么样子,决不是说它应该显示来自非Java语言的正确代码。所以,如果您反汇编Groovy,最好不要期望正确的Java代码


在这种情况下,我怀疑JD-GUI遇到了一个我们尚未摆脱的解决方案。在一些情况下,我们在方法末尾添加死代码,const_null,areturn,您已经注意到了。我们这样做是因为如果在方法末尾使用字节码标签,验证器会出现问题。由于死代码不会影响正确性,我们目前正在使用此解决方案。

我注意到自动添加的无聊设置器是简单的
this.x=param
表单,没有其他内容。为什么那个代码避免了冗余?因为在某些情况下我们设法避免了死代码部分。需要明确的是:这种死代码并不是真正需要的。它的存在主要是为了满足验证器的要求,这是由于字节码后端的内部架构无法重新排列字节码地址以避免这种需要。因此,在某些情况下,代码是编写的,而在其他情况下不是。
private static void createSetter(FieldNode field) {
    Parameter parameter = GeneralUtils.param(field.getType(), field.getName());

    BlockStatement body = new BlockStatement();
    body.addStatement(assignS(fieldX(field), varX(parameter)));

    MethodCallExpression setterCall = callX(varX(parameter), "setOwner", varX("this", field.getDeclaringClass()));
    setterCall.setType(ClassHelper.VOID_TYPE);
    body.addStatement(stmt(setterCall));

    MethodNode method = new MethodNode(setterName(field.getName()), ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] {parameter}, ClassNode.EMPTY_ARRAY, body);
    field.getDeclaringClass().addMethod(method);
}
public void setMore(Simple_MoreStuff more) {
    Simple_MoreStuff localSimple_MoreStuff = more;
    this.more = localSimple_MoreStuff;
    more.setOwner(this);
    null;
}
//TODO: set correct type here
// if setting type and a methodcall is the last expression in a method,
// then the method will return null if the method itself is not void too!
// (in bytecode after call: aconst_null, areturn)