Java StackOverflowError при компиляции метода клонирования - PullRequest
0 голосов
/ 31 августа 2009

Есть классы:

InterfaceInterval<C extends Comparable<C>, I extends InterfaceInterval<C, I>> extends Comparable<InterfaceInterval<C, ?>>
AbstractInterval<C extends Comparable<C>, I extends AbstractInterval<C, I>> implements InterfaceInterval<C, I>, Serializable, Cloneable
AbstractTimeInterval<I extends AbstractTimeInterval<I>> extends AbstractInterval<Date, I>
SortedIntervalsList<C extends Comparable<C>, I extends AbstractInterval<C, ?>> extends ArrayList<I>
Timeline extends SortedIntervalsList<Date, AbstractTimeInterval<?>>

и теперь добавляем эту строку:

Timeline t = (Timeline) super.clone();

метод clone () в классе Timeline, который я получаю:

mvn -e clean compile
The system is out of resources.
Consult the following stack trace for details.
java.lang.StackOverflowError
    at com.sun.tools.javac.code.Type$WildcardType.isSuperBound(Type.java:435)
    at com.sun.tools.javac.code.Types$1.visitWildcardType(Types.java:102)
    at com.sun.tools.javac.code.Types$1.visitWildcardType(Types.java:98)
    at com.sun.tools.javac.code.Type$WildcardType.accept(Type.java:416)
    at com.sun.tools.javac.code.Types$MapVisitor.visit(Types.java:3232)
    at com.sun.tools.javac.code.Types.upperBound(Types.java:95)
    at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2986)
    at com.sun.tools.javac.code.Types.adapt(Types.java:3016)
    at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2977)
    at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2986)
    at com.sun.tools.javac.code.Types.adapt(Types.java:3016)
    ...
    at org.apache.maven.plugin.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:516)
    at org.apache.maven.plugin.CompilerMojo.execute(CompilerMojo.java:114)
    at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:451)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:558)
    ... 16 more

НО, когда я комментирую эту строку:

//Timeline t = (Timeline) super.clone();

и

mvn compile
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
...

затем снова раскомментируйте эту строку:

Timeline t = (Timeline) super.clone();

и

mvn compile
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
...

Так что он отлично работает без малейшей помощи;). На Eclipse это работает также: /. Что я должен делать? Это ошибка компилятора Java или что-то?

Полный консольный журнал.

Ответы [ 2 ]

2 голосов
/ 31 августа 2009

Почти никогда не бывает хорошей идеей допустить ошибку в компиляторе или JVM. Вы решите свои проблемы намного быстрее, если предположите, что проблема заключается в вас и вашем коде - сначала, в прошлом, и всегда. Обязательно выполните поиск в базе данных ошибок или в Google, чтобы узнать, сталкивался ли кто-либо еще с вашей проблемой. (Это первое, что я делаю, когда получаю исключение.) Но вы обнаружите, что JVM существовал дольше и имел больше пользователей, сообщающих об ошибках, чем ваш код, поэтому вероятность того, что проблема заключается в вашем коде или ошибочное предположение о том, как все «должно» работать.

Проблема очевидна: у вас есть ситуация, когда клон одного класса вызывает другой, который вызывает первый, который вызывает другой снова, добавляя вызовы в стек вызовов до тех пор, пока он не переполнится. Удаление вызова super.clone () прерывает цикл.

Может быть, хорошее место для начала: почему ваш класс Timeline переопределяет метод clone? Что дает вам то, чего не имеет приличный конструктор копирования? Возможно, это действительно проблема дизайна.

1 голос
/ 31 августа 2009

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

Если присмотреться, то выглядит очень плохо (обратите внимание на все I с):

AbstractTimeInterval<I extends AbstractTimeInterval<I>> extends AbstractInterval<Date, I>

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

Timeline extends SortedIntervalsList<Date, AbstractTimeInterval<?>>

до

Timeline extends SortedIntervalsList<Date, AbstractInterval<Date,?>>
...