Jenkins pipeline java.io.NotSerializableException java.util.regex.Matcher错误,即使使用@NonCPS

Jenkins pipeline java.io.NotSerializableException java.util.regex.Matcher错误,即使使用@NonCPS,jenkins,jenkins-pipeline,Jenkins,Jenkins Pipeline,我在执行正则表达式匹配的Jenkinsfile函数前面使用@NonCPS,即使使用@NonCPS注释,我仍然会得到java.io.notserializableeexception java.util.regex.Matcher错误 注意,它多次调用该函数,只有在实际匹配时才会发生异常 这是我的密码: @NonCPS def extractEndTime(日志行){ def MY_REGEX=/.*(20[0-9]{2}-[0-9]{2}-[0-9]{2})。([0-9]{2}:[0-9]{2}

我在执行正则表达式匹配的
Jenkinsfile
函数前面使用
@NonCPS
,即使使用
@NonCPS
注释,我仍然会得到
java.io.notserializableeexception java.util.regex.Matcher
错误

注意,它多次调用该函数,只有在实际匹配时才会发生异常

这是我的密码:

@NonCPS
def extractEndTime(日志行){
def MY_REGEX=/.*(20[0-9]{2}-[0-9]{2}-[0-9]{2})。([0-9]{2}:[0-9]{2}:[0-9]{2})。*\“\w+\”\s文本\s(\w+)/
m=(logLine=~TEST\u logLine\u END\u REGEX)
如果(m.count){
返回[m[1],m[2],m[3]]
}否则{
返回空
}
}
执行jenkins构建时的输出:

GitHub has been notified of this commit’s build result
java.io.NotSerializableException: java.util.regex.Matcher
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)
    at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
    at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
    at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
    at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
    at java.util.LinkedHashMap.internalWriteEntries(LinkedHashMap.java:333)
    at java.util.HashMap.writeObject(HashMap.java:1354)
    at sun.reflect.GeneratedMethodAccessor116.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
    at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
    at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
    at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
    at com.cloudbees.groovy.cps.SerializableScript.writeObject(SerializableScript.java:26)
    at sun.reflect.GeneratedMethodAccessor145.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
    at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
    at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
    at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
    at java.util.HashMap.internalWriteEntries(HashMap.java:1777)
    at java.util.HashMap.writeObject(HashMap.java:1354)
    at sun.reflect.GeneratedMethodAccessor116.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
    at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.writeObject(RiverWriter.java:132)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:433)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:412)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:357)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:78)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:236)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:224)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:63)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: an exception which occurred:
    in field delegate
    in field closures
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@42b37962
Finished: FAILURE

可能是由于
m
变量范围。 尝试使用
def
限制它,如下所示:

defm=(logLine=~TEST\u logLine\u END\u REGEX)

如果不使用
def
,则会在全局脚本绑定中创建一个变量,因此退出该方法后该变量仍然存在。

Jenkins要求所有变量都可序列化,因为在出现服务器重启等中断时,管道的状态会定期保存到磁盘。此功能允许管道保持其状态并在服务器重新启动后继续。Matcher类型的变量不可序列化,需要开发人员进行一些额外的工作

发件人:

然而,最安全的方法是隔离非序列化状态的使用 在用注释@NonCPS标记的方法中。这种方法将 被管道引擎及其局部变量视为“本机” 从未保存过

代码示例提供了:

@NonCPS
def version(text) {
  def matcher = text =~ '<version>(.+)</version>'
  matcher ? matcher[0][1] : null
}
@NonCPS
def版本(文本){
def matcher=text=~'(.+)'
匹配器?匹配器[0][1]:空
}
支持这一点的其他材料可以在上找到,这里他们讨论了标有
@NonCPS
的方法的更多技术细节和行为

管道脚本可以用注释标记指定的方法 @非现金。然后正常编译这些文件(沙盒安全性除外) 检查),因此其行为非常类似于Java中的“二进制”方法 平台、Groovy运行时或Jenkins核心或插件代码@非现金 方法可以安全地使用不可序列化的对象作为局部变量, 尽管它们不应接受不可序列化的参数或返回或 存储不可序列化的值。你不能打普通电话 (CPS转换)方法或管道步骤,来自@NonCPS方法, 因此,在通过考试之前,最好使用它们进行一些计算 返回到主脚本的摘要。请特别注意@Overrides 在二进制类中定义的方法,例如Object.toString(), 通常应标记为@NonCPS,因为它通常是二进制的 给他们打电话

见:
而且

为了清楚起见,以下几点对我很有用

开发人员的额外工作,例如,请参见下面的代码

my.Parameter不可序列化

所以我创建了一个没有def的方法,并将其注释为@NonCPS,然后从节点块调用它

  node('MySys') {
    echo 'hello'
    avoidCPS()
    echo 'finished'
  }

  @NonCPS
  avoidCPS () {
    // use my.Parameter here
    my.Parameter p = new my.Parameter()
    ... do some more ...
  }
以下工作(请注意
[0]
):

但这会导致
java.io.NotSerializableException

def m = (it =~ /abcd/)

@DanielPark如果这是个好答案,您应该将其标记为已接受的,并且向上投票也是一种良好的做法:-)我不认为范围界定是这里的问题,因为Jenkins希望管道是可序列化的,并且抛出
java.io.NotSerializableException:java.util.regex.Matcher
异常是因为管道试图保存一个不可用的变量的状态不可序列化。请参阅下面我的答案。我已经在使用
def
,但是我收到了这个错误。到目前为止,无法理解导致此错误的原因:(我有两个
def g=m.group(1)
类调用,如果我对它们进行注释,错误就会消失。这真的很奇怪!我实际上在上面得出了一个错误的结论。
Matcher.group()
调用不是问题,但下一行使用提取的字段,即使它是一个简单的回显,比如
echo“g1=${g1}g2=${g2}”
。由于
g1
g2
是简单的字符串,没有引用
Matcher
,这毫无意义,但这不是我第一次在Jenkins管道中看到无法解释的错误。解决方法是将使用
Matcher
的代码推送到函数中,并从中返回组。这就是问题所在虽然我没有将其声明为
NonCPS
,但已解决。因为
m
的声明方式是这样的(没有
def
或任何使其成为本地的东西),我相信它的作用域是“全局”的,这就是序列化异常发生的原因。“管道将所有变量限制为可序列化类型”-在同一文档中:“虽然普通管道仅限于可序列化的局部变量(见底部的附录),@NonCPS函数可以在内部使用更复杂、不可序列化的类型(例如正则表达式匹配器等)。"-我很有信心这是因为
m
是一个,并且在
@NonCPS
的范围内为它分配了一个不可序列化的类型,这就是为什么我认为另一个答案是正确的。我找不到任何说明脚本全局变量被注释为
@NonCPS
的文档。上面的最佳实践链接没有列出scipt g作为常见的非序列化类型的全局变量。此外,如果脚本化全局变量可以作为非序列化类型使用,则除非它们的作用域是一个用
@NonCPS
属性注释的函数,否则使用它们是不安全的。我认为使用
@NonCPS
函数是解决方案,或许您可以将其添加到您的答案中ad仅链接到解决方案;链接往往会断开。在使用非序列化类时,是否必须删除“def”语句?
def m = (it =~ /abcd/)