【问题标题】:Jenkins Groovy StackOverFlowError when accessing a property访问属性时出现 Jenkins Groovy StackOverFlowError
【发布时间】:2018-09-16 02:48:13
【问题描述】:

我正在尝试编写一个小型工作 DSL,但在访问类属性时遇到java.lang.StackOverflowError 错误。

因此,甚至不需要复杂的脚本。请参阅以下脚本

class Komponente {

  String name

  Komponente(name) {
    this.name = name
  }

  String getName() {
    return this.name
  }  

  String toString() {
    return 'Klasse: Komponente (name: [' + this.name +'])'
  }
}

Komponente komponente = new Komponente('Testkomponente')

println 'Erstellte Komponente: ' + komponente.getName()

Groovy web console 上运行它时效果很好,但是在我的 Jenkins 中运行它时我得到:

FATAL: null
java.lang.StackOverflowError
  at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:1038)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:406)
  at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:677)
  at groovy.lang.GroovyClassLoader$InnerLoader.loadClass(GroovyClassLoader.java:425)
  at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:787)
  at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:775)
  at sun.reflect.GeneratedMethodAccessor316.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
  at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1850)
  at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3758)
  at Komponente.getProperty(script)
  at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174)
  at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456)
  at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:290)
  at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
  at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:257)
  at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:288)
  at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:292)
  at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$2.callStatic(Unknown Source)
  at Komponente.getName(script:10)
  at sun.reflect.GeneratedMethodAccessor316.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
  at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1850)
  at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3758)
  at Komponente.getProperty(script)
  at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174)
  at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456)
  at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:290)
  at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
  at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:257)
  at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:288)
  at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:292)
  at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$2.callStatic(Unknown Source)
  at Komponente.getName(script:10)
  ...

  (As you can see this repeates)

如何访问在 Jenkins 上运行的 Groovy 脚本中的类属性,而不会出现 StackOverflowError 异常?

我的系统:

  • Jenkins 版本为 2.73.3
  • JobDSL 插件 1.68
  • 订书机 Groovy 模块org.kohsuke.stapler:stapler-groovy:1.250
  • Apache Groovy org.codehaus.groovy:groovy-all:2.4.11

我已经对此错误消息进行了一些搜索,但我发现的所有 Jenkins-Issues 至少在 2.7.1 中已修复并关闭,因此应该包含在我的 jenkins 版本中。

【问题讨论】:

    标签: jenkins groovy jenkins-job-dsl


    【解决方案1】:

    从您的课程中删除 getName() 方法。当您指定像 String name 这样的类字段时,您会得到方法 String getName()void setName(String name) 开箱即用。

    请记住,Jenkins Groovy 脚本执行环境与普通的 Groovy 略有不同(例如在 Groovy 控制台中) - Jenkins 使用 groovy-cps 执行环境。

    在您的情况下,以下类 org.kohsuke.groovy.sandbox.impl.Checker 导致错误 - 根据您的堆栈跟踪调用 Komponente.getName() 通过以下执行链触发 Komponente.getProperty() 方法:

      at Komponente.getProperty(script)
      at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174)
      at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:456)
      at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:290)
      at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68)
      at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:257)
      at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:288)
      at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:292)
      at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$2.callStatic(Unknown Source)
      at Komponente.getName(script:10)
    

    Komponente.getProperty() 触发了Komponente.getName() 并且您遇到了导致StackOverflowError 的无限循环。

    当我将你的类复制到我的测试管道脚本时发生了类似的问题,这是我得到的堆栈跟踪:

    Started by user admin
    [Pipeline] End of Pipeline
    java.lang.StackOverflowError: Excessively nested closures/functions at Komponente.getName(WorkflowScript:10) - 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.GeneratedMethodAccessor106.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
        at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
        at com.cloudbees.groovy.cps.Next.step(Next.java:83)
        at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
        at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
        at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
        at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
        at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
        at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:19)
        at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:35)
        at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:32)
        at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
        at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:32)
        at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:174)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:331)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:82)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:243)
        at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:231)
        at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
        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)
    Finished: FAILURE
    

    它不像你的那么简单,但它是由同一件事引起的。当我删除 String getName() 方法时,它按预期工作。它也应该对你有用。希望对您有所帮助。

    【讨论】:

    • 哇——我在风格指南中读到你不需要创建getter/setter,但因为我来自java,这是我第一次写groovy,这对我来说更容易——由于它在 Web 控制台中运行,我没想到这可能是个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 2017-07-05
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 2022-12-19
    相关资源
    最近更新 更多