Stackoverflow вызывает метод metaClass на карте - PullRequest
1 голос
/ 11 марта 2011

Этот фрагмент кода вызывает исключение 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)

snip

Я не уверен, что это актуально, но ASObject является подклассом Map, и его содержимое может иметь свойства, которые ссылаются на другие ключи внутри себя.

IЯ бы подумал, что это актуально, за исключением того, что StackOverflow указывает на то, что groovy пересекает элементы карты.

Что происходит?Почему происходит этот стекопоток?

Ответы [ 2 ]

1 голос
/ 11 марта 2011

assert result.isNotLazyProxy, вероятно, не делает то, что вы хотите сделать.

В Groovy map.somehing переводится как map.get(something). См http://groovy.codehaus.org/JN1035-Maps:

assert map2.class == null
// синтаксис поля всегда ссылается на значение ключа, даже если он не существует
// используем getClass () вместо класса для карт ...
assert map2.getClass () == LinkedHashMap // тип используемой карты

Так что используйте assert result.isNotLazyProxy().

Конечно, result.isNotLazyProxy должен возвращать ноль в вашем случае, и утверждение assert result.isNotLazyProxy должно потерпеть неудачу. Когда это утверждение не выполняется, Groovy отобразит ошибку подтверждения и карту. В вашем случае форматирование карты по какой-то причине не удается.

Причина, по которой он не работает:

Это известная ошибка , см. пример . Как я вижу, он не имеет ничего общего с ASObject , так как не использует списки.

0 голосов
/ 11 марта 2011

На первый взгляд кажется, что что-то еще вызывает бесконечную рекурсию ...

Есть ли у ASObject какие-либо другие методы метакласса?Особенно те, которые переопределяют getAt( key ) метод Map

. Я придумал этот скрипт быстрого теста, и он, кажется, работает нормально, как я и ожидал (и я думаю, так и есть.так же, как вы говорите, вы делаете)

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

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

assert new ASObject().isNotLazyProxy()
...