Stackoverflow在Map上调用metaClass方法

时间:2011-03-11 13:39:00

标签: java groovy stack-overflow

这段代码导致stackOverflow异常:

ISerializer serializer = buildSerializer(TestDataProvider.getAuthor());
ASObject result = (ASObject) serializer.serialize();
assert result.isNotLazyProxy

StackOverflow正在抛出这一行:assert result.isNotLazyProxy。请注意,isNotLazyProxy方法实际上从未被调用过。

isNotLazyProxy是一个扩展方法(在groovy中调用的是什么?)定义如下:

/**
 * Asserts that this ASObject is not a lazy loaded proxy,
 * ie - that all of it's properties' values have been included
 */
ASObject.metaClass.isNotLazyProxy = { ->
    assert delegate[HibernateProxyConstants.PROXYINITIALIZED] == true
    return true;
}

但是,在该闭包的第一行设置断点表明它永远不会被调用。

相反,抛出了StackOverflow:

java.lang.StackOverflowError
    at java.lang.System.arraycopy(Native Method)
    at java.lang.String.getChars(String.java:855)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:391)
    at java.lang.StringBuffer.append(StringBuffer.java:224)
    at java.lang.StringBuffer.<init>(StringBuffer.java:104)
    at org.codehaus.groovy.runtime.InvokerHelper.formatMap(InvokerHelper.java:557)
    at org.codehaus.groovy.runtime.InvokerHelper.format(InvokerHelper.java:530)
    at org.codehaus.groovy.runtime.InvokerHelper.formatList(InvokerHelper.java:602)
    at org.codehaus.groovy.runtime.InvokerHelper.format(InvokerHelper.java:527)
    at org.codehaus.groovy.runtime.InvokerHelper.formatMap(InvokerHelper.java:575)

剪断

我不确定它是否相关,但ASObjectMap的子类,它的内容可能具有引用其自身内部其他键的属性。

我会认为它是相关的,除了StackOverflow似乎表明groovy正在遍历地图的成员。

发生了什么事?为什么会发生这种堆栈溢出?

2 个答案:

答案 0 :(得分:1)

assert result.isNotLazyProxy可能没有做你想做的事。

在groovy中,map.somehing被翻译为map.get(something)。见http://groovy.codehaus.org/JN1035-Maps

  

断言map2.class == null
  //字段语法总是指key的值,即使它不存在   //使用getClass()而不是类的地图...
  assert map2.getClass()== LinkedHashMap //正在使用的地图类型

所以请使用assert result.isNotLazyProxy()

当然result.isNotLazyProxy在你的情况下应该返回null,并且assert result.isNotLazyProxy断言应该失败。当这个断言失败时,groovy会显示一个断言错误和地图。在您的情况下,由于某种原因格式化地图失败。

失败的原因:

这是known bug,请参阅example。我认为它与ASObject无关,因为它不使用列表。

答案 1 :(得分:0)

乍一看,看起来其他东西正在导致无休止的递归...

ASObject是否有其他metaClass方法?特别是那些覆盖getAt( key )

Map方法的人

我想出了这个快速测试脚本,它看起来像我期望的那样正常工作(而且我认为它和你说的那样做的相同)

class ASObject {
  @Delegate Map map = [ 'PROXYINITIALIZED' : true ]
}

ASObject.metaClass.isNotLazyProxy = { ->
    assert delegate[ 'PROXYINITIALIZED' ] == true
    return true
}

assert new ASObject().isNotLazyProxy()