Задачи Ant выдают исключение StackOverflowException

Я пытаюсь скомпилировать более 100 классов Java из разных пакетов из чистого каталога (без дополнительных компиляций), используя следующие задачи муравья:

<target name="-main-src-depend">
    <depend srcdir="${src.dir}" 
            destdir="${bin.dir}" 
            cache="${cache.dir}"
            closure="true"/>
</target>   

<target name="compile" depends="-main-src-depend"
        description="Compiles the project.">

    <echo>Compiling</echo>

    <javac  target="${javac.target}"
            source="${javac.source}"
            debug="${javac.debug}"
            srcdir="${src.dir}"
            destdir="${bin.dir}">
        <classpath>
            <path refid="runtime.classpath"/>
            <path refid="compile.classpath"/>
        </classpath>
    </javac>
</target>

Однако при первом запуске задачи компиляции всегда возникает исключение StackOverflowException. Если я снова запускаю задачу, компилятор выполняет инкрементную сборку, и все работает нормально. Это нежелательно, поскольку мы используем CruiseControl для автоматической ежедневной сборки, что приводит к ложным сбоям сборки.

В качестве быстрого и грязного решения я создал 2 отдельные задачи, компилируя части проекта в каждой. Я действительно не думаю, что это решение сохранится, поскольку в будущем будет добавлено больше классов, и я не хочу добавлять новые задачи компиляции каждый раз, когда мы достигаем «предела компиляции».

19.08.2008 20:53:53
Это вызывает исключение StackOverflowException - так что вы обвиняете нас? :-)
kenj0418 25.06.2009 05:10:55
@ kenj0418 - Ваш комментарий действительно заставил меня почесать голову, пока я не увидел смайлик. Неплохо!
Elliot Vargas 25.06.2009 18:18:19
6 ОТВЕТОВ
РЕШЕНИЕ

Будет приятно узнать; что может вызвать или вызывает StackOverflowError во время компиляции кода Java?

Вполне вероятно, что оценка длинного выражения в вашем java-файле потребляет много памяти, и поскольку это делается в сочетании с компиляцией других классов, виртуальной машине просто не хватает места в стеке. Ваш сгенерированный класс, возможно, выдвигает законные пределы для его содержания. Смотрите главу 4.10 Ограничения виртуальной машины Java в спецификации виртуальной машины Java, Second Edition .

Исправление 1: рефакторинг класса

Так как ваш класс генерируется, это может быть не вариант. Тем не менее, стоит взглянуть на варианты, которые предлагает ваш инструмент генерации классов, чтобы увидеть, может ли он создать что-то менее хлопотное.

Исправление 2: увеличение размера стека

Я думаю, что у Кирона есть одно решение, когда он упоминает аргумент -Xss. javac принимает несколько нестандартных аргументов, которые будут различаться в зависимости от версии и поставщика компилятора.

Мой компилятор:

$ javac -version
javac 1.6.0_05

Чтобы перечислить все варианты для этого, я бы использовал эти команды:

javac -help
javac -X
javac -J-X

Я думаю, что ограничение стека для Javac по умолчанию составляет 512 КБ. Вы можете увеличить размер стека для этого компилятора до 10 Мб с помощью этой команды:

javac -J-Xss10M Foo.java

Возможно, вы сможете передать это в файл Ant с элементом compilerarg, вложенным в вашу задачу javac .

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
    <compilerarg value="-J-Xss10M" />
</javac>
5
23.05.2017 10:27:42
Последняя часть этого ответа приведет к ошибке от javac. Пожалуйста, посмотрите этот ответ: stackoverflow.com/questions/16935/…
npellow 25.06.2009 04:51:27
Добавление пробела вызывает эту ошибку с Sun javac 1.6.0_05 на WinXP: "java.lang.NoClassDefFoundError: -Xss10M" ... Я предполагаю, что это должно зависеть от компилятора.
McDowell 25.06.2009 09:28:41

Это происходит при запуске команды javac из командной строки? Возможно, вы захотите попробовать атрибут fork .

1
26.01.2011 00:13:33

Попробуйте добавить несколько вариантов этих атрибутов в строку задач Antjavac :

memoryinitialsize="256M" memorymaximumsize="1024M"

Вы также можете попробовать fork="true", не уверенный, позволяет ли это вам устанавливать значения для стека и кучи (aka -Xm1024), но это может помочь (если это будет работать из командной строки, но не в Ant).

[Редактировать]: добавлена ​​ссылка - кажется, что страница javacзадач предполагает, что для указанных выше параметров также необходимо установить fork="true".

1
24.01.2011 00:12:18

Это довольно странно, 100 классов на самом деле не так много. Что делает компилятор при переполнении стека? Создана ли полезная трассировка стека? Что произойдет, если вы запустите javacкоманду прямо из командной строки, а не через муравей?

Один из возможных обходных путей - просто увеличить размер стека, используя -Xssаргумент JVM; либо для работающей JVM, antлибо путем установки fork="true"и a <compilerarg>в <javac>задаче. На самом деле, теперь, когда я думаю об этом, проблема уходит, просто вставив fork="true"?

0
19.08.2008 21:21:16

Вот что я нашел. После публикации моего вопроса я продолжил и изменил задачу компиляции с атрибутами fork="true", memoryinitialsize="256m"и memorymaximumsize="1024m"(сегодня обнаружил, что это было предложено Kieron и jmanning2k, спасибо за ваше время). Это не решило проблему, тем не менее.

Я решил начать удалять классы из дерева исходных текстов, чтобы посмотреть, может ли проблема определить проблему. Оказывается, у нас был класс клиента Web-сервиса для Axis 1.4, который был автоматически сгенерирован из файла WSDL. Теперь этот класс является монстром (как во Франкенштейне), он имеет 167 членов поля (все из них имеют тип String), 167 пар получатель / установщик (1 для каждого поля), конструктор, который получает все 167 полей в качестве параметров, метод equals, который сравнивает все 167 полей странным образом. Для каждого поля сравнение выглядит так:

(this.A == null && other.getA() == null) || (this.A != null && this.A.equals(other.getA()))

Результатом этого сравнения является «anded» (&&) с результатом сравнения следующего поля и так далее. Класс продолжает метод hashCode, который также использует все поля, некоторые пользовательские методы сериализации XML и метод, который возвращает объект метаданных, специфичный для Axis, который описывает класс и который также использует все члены поля.

Этот класс никогда не изменяется, поэтому я просто помещаю скомпилированную версию в путь к классам приложения, и проект компилируется без проблем.

Теперь я знаю, что удаление этого единственного исходного файла решило проблему. Тем не менее, я понятия не имею, почему именно этот класс вызвал проблему. Будет приятно узнать; что может вызвать или вызывает StackOverflowError во время компиляции кода Java? Я думаю, я отправлю этот вопрос.

Для тех, кто заинтересован:

  • Windows XP SP2
  • СОЛНЦЕ JDK 1.4.2_17
  • Муравей 1.7.0
0
20.08.2008 14:23:06
  <javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
      <compilerarg value="-J-Xss10M" />
    </javac>

из комментария выше неверно. Вам нужен пробел между -J и -X, вот так:

<javac srcdir="gen" destdir="gen-bin" debug="on" fork="true">
    <compilerarg value="-J -Xss10M" />
</javac>

чтобы избежать следующей ошибки:

 [javac] 
[javac] The ' characters around the executable and arguments are
[javac] not part of the command.
[javac] Files to be compiled:

... [javac] javac: недопустимый флаг: -J-Xss1m [javac] Использование: javac

2
23.05.2017 12:33:26