Groovy 关闭检查导致意外堆栈溢出错误
我试图使用此代码更好地理解Groovy 关闭检查导致意外堆栈溢出错误,groovy,closures,stack-overflow,Groovy,Closures,Stack Overflow,我试图使用此代码更好地理解this、owner和delegate如何在Groovy闭包中工作: class GroovyTest { static void main(String[] args) { examine() { println 'In first closure' println "class is ${getClass().name}" println "
this
、owner
和delegate
如何在Groovy闭包中工作:
class GroovyTest {
static void main(String[] args) {
examine() {
println 'In first closure'
println "class is ${getClass().name}"
println "this is $this, super: ${this.getClass().getSuperclass().name}"
println "owner is $owner, super: ${owner.getClass().getSuperclass().name}"
println "delegate is $delegate, super: ${delegate.getClass().getSuperclass().name}"
examine() {
println 'In closure within the closure'
println "class is ${getClass().name}"
println "this is $this, super: ${this.getClass().getSuperclass().name}"
println "owner is $owner, super: ${owner.getClass().getSuperclass().name}"
println "delegate is $delegate, super: ${delegate.getClass().getSuperclass().name}"
}
}
}
static examine(closure) {
closure()
}
}
当我执行这段代码时,它会导致堆栈溢出错误,但是我很难找出导致无限递归的原因。我在这里包括堆栈跟踪的一部分:
Caught: java.lang.StackOverflowError
java.lang.StackOverflowError
at GroovyTest$_main_closure1.doCall(GroovyTest.groovy:10)
at jdk.internal.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at GroovyTest$_main_closure1$_closure2.doCall(GroovyTest.groovy:14)
at GroovyTest$_main_closure1$_closure2.doCall(GroovyTest.groovy)
at jdk.internal.reflect.GeneratedMethodAccessor8.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at GroovyTest.examine(GroovyTest.groovy:21)
at jdk.internal.reflect.GeneratedMethodAccessor7.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at GroovyTest$_main_closure1.doCall(GroovyTest.groovy:10)
at jdk.internal.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at GroovyTest$_main_closure1$_closure2.doCall(GroovyTest.groovy:14)
at GroovyTest$_main_closure1$_closure2.doCall(GroovyTest.groovy)
at jdk.internal.reflect.GeneratedMethodAccessor8.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at GroovyTest.examine(GroovyTest.groovy:21)
似乎行println“owner是$owner,super:${owner.getClass().getSuperclass().name}”
导致了无限递归
为什么这段代码会导致堆栈溢出错误,我可以做些什么来修复它
编辑:以下脚本也包含嵌套闭包,完全按照预期工作。堆栈溢出异常不是由嵌套闭包本身引起的。这似乎与打印声明有关
def examiningClosure(closure) {
closure()
}
examiningClosure() {
println "In First Closure:"
println "class is " + getClass().name
println "this is " + this + ", super:" + this.getClass().superclass.name
println "owner is " + owner + ", super:" + owner.getClass().superclass.name
println "delegate is " + delegate +
", super:" + delegate.getClass().superclass.name
examiningClosure() {
println "In Closure within the First Closure:"
println "class is " + getClass().name
println "this is " + this + ", super:" + this.getClass().superclass.name
println "owner is " + owner + ", super:" + owner.getClass().superclass.name
println "delegate is " + delegate +
", super:" + delegate.getClass().superclass.name
}
}
好的,我首先要为没有花时间仔细调查此事道歉 我会试图用实际的解释来弥补 结果显示以下代码:
def c = {
println "foo"
}
println "${c}"
有些不直观的结果是执行闭包,而不是在std out上打印闭包的字符串表示:
─➤ groovy test.groovy
foo
因此,在您的示例中:
class GroovyTest {
static void main(args) {
examine { // closure 1
examine { // closure 2
println "${owner}"
}
}
}
static examine(closure) {
closure()
}
}
(可以省略检查方法调用后的参数)
最里面的闭包的所有者是最里面的闭包本身。调用封闭闭包将导致自调用的无限递归,并最终导致StackOverflowException
例如,您可以通过执行println“${owner.getClass()}”
来解决此问题,这会阻止隐式闭包调用
我不得不说,来自“${closure}”
的闭包调用非常不直观,完全不是我所期望的……在多年使用groovy之后……但它确实存在。您在检查
中已经执行的闭包中调用检查
,从而导致无限深度的递归。这或多或少就是StackOverflowException
的定义。如果删除第二个呼叫,它应该会消失。也就是说,您运行examine
它调用examine
它再次调用examine
它再次无限地调用examine
。@MatiasBjarand第一个闭包只调用第二个闭包。为什么这必然会导致堆栈溢出错误?这封信中没有任何内容可以说明问题。第一个方法调用包含一个闭包,该闭包包含第二个方法调用。第二个嵌套的方法调用本身不包含方法调用,因此它应该以此结束。Groovy允许嵌套闭包。这不是导致错误的原因。堆栈跟踪表明问题与此行有关:println“owner是$owner,super:${owner.getClass().getSuperclass().name}”
FYI。。。您的问题场景可以简化很多,使问题更容易处理。看,这个文件中的案例就是我们在这里看到的例子吗。或者这是别的什么?