【问题标题】:Jenkins scripted pipleline @NonCPS and StackOverflowErrorJenkins 脚本化流水线 @NonCPS 和 StackOverflowError
【发布时间】:2021-03-07 06:35:49
【问题描述】:

我有简单的管道脚本:

#!groovy

@org.jenkinsci.plugins.workflow.libs.Library('Some@lib')

import com.cloudbees.groovy.cps.NonCPS

node() {

    echo CheekyEnum.getByName('name1').getName()

}

enum CheekyEnum {

    ENUM_1('name1', 'f1'),
    ENUM_2('name2', 'f2')

    String name
    String field

    CheekyEnum(String name, String field) {
        this.name = name
        this.field = field
    }

    static CheekyEnum getByName(String name) {
        return values().find { it.name == name }
    }
    
    String getName() {
        return name
    }
}

当我运行它时,一切正常,但是如果方法getName()有一点变化@

@NonCPS
String getName() {
    return name
}

我得到一个很长的错误堆栈跟踪:

java.lang.StackOverflowError
    at java.lang.ClassLoader.loadClass(ClassLoader.java:398)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxResolvingClassLoader.lambda$loadClass$0(SandboxResolvingClassLoader.java:51)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxResolvingClassLoader.lambda$load$2(SandboxResolvingClassLoader.java:85)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$doComputeIfAbsent$14(BoundedLocalCache.java:2337)
    at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1892)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.doComputeIfAbsent(BoundedLocalCache.java:2335)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2318)
    at com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:111)
    at com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:54)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxResolvingClassLoader.load(SandboxResolvingClassLoader.java:79)
    ...

为什么? @NonCPS 不是把方法排除在 CPS 转换之外吗?

【问题讨论】:

    标签: groovy jenkins-pipeline jenkins-groovy cps


    【解决方案1】:

    enum 本身是一种可序列化的类型。所以你最好为它创建一个包装函数:

    import com.cloudbees.groovy.cps.NonCPS
    
    node() {
    
        echo getName(CheekyEnum.getByName('name1'))
    
    }
    ...
    @NonCPS
    String getName(CheekyEnum cheeky) {
        return cheeky.name
    }
    

    相关的 StackOverflowError 可能workflow-cps-plugin 中的错误/异味。请看一下它的Technical design

    管道脚本可以用注解@NonCPS 标记指定的方法。然后正常编译这些文件(沙盒安全检查除外)。

    您在 Groovy 沙箱中运行的 AFAICS。沙盒拦截器 可能正在生成此堆栈溢出。在沙盒之外运行也应该可以解决您的问题。

    顺便说一句,您还可以阅读 Pipeline CPS Method Mismatches 以更好地了解在非 CPS 转换代码中可以调用的内容。

    【讨论】:

    • 对不起,我没听懂。 Enum 是可序列化的,那么,是不是意味着我们不应该对 CPS 有任何问题?为什么需要包装器?
    • @RedMurloc 你用NonCPS注释了这个方法,所以这就是为什么一个可序列化的类型会导致问题。
    猜你喜欢
    • 2017-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多