gpt4 book ai didi

Jenkins 解释一行上的多个对象声明

转载 作者:行者123 更新时间:2023-12-03 16:08:21 26 4
gpt4 key购买 nike

这不是问题,而是一个警告性的故事:
我试图节省一些空间,并在Jenkins Declarative管道中声明了变量,如下所示:

int a, b, c

然后,我将它们初始化为:
a = b = c = 0

在我的代码中,我将这些整数用作for循环中的计数器。我的脚本一遍又一遍地失败,抛出了一些异常:
java.lang.NullPointerException: Cannot invoke method next() on null object

而且我肯定知道我的 list 是经过硬编码的,因此是有效的。
因此,我开始想知道这些计数器是怎么回事,当我在它们上调用getClass()时, Jenkins 高兴地告诉我它们不是整数,而是
org.codehaus.groovy.runtime.NullObject

将代码更改为
int a = 0
int b = 0
int c = 0

一切都像魅力一样。
只是想分享这个。也许它将帮助某人节省一些挫败感。

最佳答案

Jenkins管道使用groovy-cps解释器以连续传递样式执行Groovy代码。这不是普通的Groovy,您可以直接在IDE或Groovy Shell中执行。

Groovy CPS转换您的代码以支持延续传递样式和正确的Groovy表达式,例如:

a = b = c = 0

被转换成更像是的东西:
eval(
var("a"),
assign(
eval(
var("b"),
assign(
eval(
var("c"),
assign(0)
)
)
)
)
)

CPS解释器中此表达式的问题在于,赋值不返回任何值,因此 null值被赋给了变量 b,并且变量 a发生了同样的事情。

如果您想深入了解CPS调用块,则可以克隆groovy-cps项目,并在 com.cloudbees.groovy.cps.CpsTransformerTest类中编写一个简单的测试用例。

@Test
void testMultiVariablesInlineCPS() {
def cps = parseCps('''
int a, b, c
a = b = c = 0
''')
println cps
}

然后,您可以在 println cps处放置一个断点并运行调试器。当您打开检查窗口时,您将看到与此类似的图片:

enter image description here

作为附带说明,请记住,当将代码编译为字节码时,Groovy编译器还会转换单行分配。如果您编译一个简单的Groovy脚本,例如:

int a, b, c
a = b = c = 0

println "$a $b $c"

然后在IDE中打开其类文件以将字节码反编译为Java等效文件,您将看到类似以下内容:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.GStringImpl;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite;

public class test extends Script {
public test() {
CallSite[] var1 = $getCallSiteArray();
}

public test(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}

public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, test.class, args);
}

public Object run() {
CallSite[] var1 = $getCallSiteArray();
int a = 0;
int b = 0;
int c = 0;
byte var5 = 0;
return var1[1].callCurrent(this, new GStringImpl(new Object[]{Integer.valueOf(var5), Integer.valueOf(var5), Integer.valueOf(var5)}, new String[]{"", " ", " ", ""}));
}
}

关于 Jenkins 解释一行上的多个对象声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61420959/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com