问题概述
在执行 Jenkins Pipeline 时,产生如下错误:
java.lang.StackOverflowError: Excessively nested closures/functions at WorkflowScript.getProjectPath(WorkflowScript:16) - look for unbounded recursion - call depth: 1025 at com.cloudbees.groovy.cps.impl.CpsFunction.invoke(CpsFunction.java:28) at com.cloudbees.groovy.cps.impl.CpsCallableInvocation.invoke(CpsCallableInvocation.java:40) at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:62) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:77) at sun.reflect.GeneratedMethodAccessor345.invoke(Unknown Source) ...
(这个错误信息是从 stackoverflow 中复制的,与我遇到的问题是同样的场景,只是我后来整理的笔记所以找不到原因了)
本文将介绍该java.lang.StackOverflowError: Excessively nested closures/functions错误的成因及处理方法;
问题原因
这一切都是因为对 Groovy 语言的不熟悉。产生问题的代码如下:
package com.k4nz.tools // 我承认我写的代码不够 Groovy 风格 class Zim { private String outputFolder = "/tmp/build" public void getOutputFoler() { return this.outputFolder } }
问题就处在上面的getOutputFoler()方法。在 Groovy 中,变量的查找是通过 GET 方法,也就是说,上述代码等价于:
package com.k4nz.tools // 我承认我写的代码不够 Groovy 风格 class Zim { private String outputFolder = "/tmp/build" public void getOutputFoler() { return this.getOutputFolder() } }
这就导致程序进入了无限的递归调用,直至最后的溢出;
在「1.6. Fields and properties/1.6.2. Properties」中描述了这一特性:在 Groovy 中,遵循 JavaBean 的约定,但提供了一种更简单的方法来定义属性……
解决办法
重命名方法,或者重命名变量;
因此,以后在 Groovy 中,使用 GET/SET 方法要小心,防止进入无限递归调用;
参考文献
Jenkins pipeline throws “StackOverflowError: Excessively nested closures/functions”
1.6. Fields and properties/1.6.2. Properties