Дженкинс выходит из кучи (OutOfMemoryError), когда тесты печатают большое количество сообщений журнала в System.out - PullRequest
2 голосов
/ 25 декабря 2011

Я использую Jenkins для запуска некоторых системных тестов.Эти тесты записывают 18-20 МБ распечаток на стандартный вывод.Задание Jenkins настроено для работы с максимальным размером кучи 2048 МБ.Как ни странно, когда эти распечатки включены, jenkins выходит OutOfMemoryError (из пространства кучи).

Определенно, распечатки вызывают проблему.Без них все работает нормально.Что меня беспокоит, так как 20 МБ текста приводят к тому, что весь процесс становится OutOfMemory.

Я уже увеличил размер кучи с 1 ГБ до 2 ГБ, но безрезультатно.Без отпечатков при максимальном размере кучи в 1 ГБ все тесты работают нормально.

Вот исключение:

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2786)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
    at java.io.PrintStream.write(PrintStream.java:430)
    at org.apache.maven.surefire.util.TeeStream.write(TeeStream.java:44)
    at java.io.PrintStream.write(PrintStream.java:430)
    at org.apache.maven.surefire.util.TeeStream.write(TeeStream.java:42)
    at java.io.PrintStream.write(PrintStream.java:430)
    at org.apache.maven.surefire.util.TeeStream.write(TeeStream.java:42)
    at java.io.PrintStream.write(PrintStream.java:430)
    at org.apache.maven.surefire.util.TeeStream.write(TeeStream.java:42)
    at java.io.PrintStream.write(PrintStream.java:430)
    at org.apache.maven.surefire.util.TeeStream.write(TeeStream.java:42)
    at java.io.PrintStream.write(PrintStream.java:430)
    at org.apache.maven.surefire.util.TeeStream.write(TeeStream.java:42)
    at java.io.PrintStream.write(PrintStream.java:430)
    at org.apache.maven.surefire.util.TeeStream.write(TeeStream.java:42)
    at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
    at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:263)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:106)
    at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190)
    at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111)
    at java.io.PrintStream.write(PrintStream.java:476)
    at java.io.PrintStream.print(PrintStream.java:619)
    at java.io.PrintStream.println(PrintStream.java:756)
    ...

Кто-нибудь знает какую-то конфигурацию Дженкинса, что много отпечатков наSystem.out (из них 20 МБ) не приведет к возникновению OutOfMemory?

Пояснение: я не хочу отлаживать Jenkins, я не являюсь разработчиком Jenkins.Я использую Jenkins для запуска системных тестов, используя JUnit для моего приложения в качестве CI.

Ответы [ 3 ]

4 голосов
/ 25 декабря 2011

Попробуйте запустить jenkins с аргументом JVM "-XX: + HeapDumpOnOutOfMemoryError", который должен дать вам файл дампа для анализа всякий раз, когда вы получаете исключение нехватки памяти.

РЕДАКТИРОВАТЬ -

Думаю, у меня есть кое-что для вас.
Во-первых, плагин surefire по умолчанию разветвляет новую JVM для выполнения тестов, и эта JVM не наследует свойства JVM JAVM maven, т. Е. Если для процесса maven задано значение Max Heap 2048 МБ, оно не будет установлено для JVM разветвляется надёжным плагином.
Поэтому для установки аргументов JVM разветвленной JVM используйте свойство argLine плагина surefire. Таким образом, вы сможете установить максимальную кучу для раздвоенной JVM, а не для maven JVM.

Во-вторых, похоже, что плагин surefire перенаправляет stdout / stderr и сохраняет в памяти содержимое, записанное в эти 2 потока, поэтому у вас может быть недостаточно памяти.
Таким образом, вы также можете попробовать установить для свойства 'redirectTestOutputToFile' значение 'true', таким образом все sdtout переходит в файл, возможно, это позволит избежать сохранения содержимого потока в памяти,
Или попробуйте установить forkmode = 'always', таким образом он будет разветвлять одну JVM на каждый тестовый класс, предотвращая накопление памяти, один тест за другим.

Надеюсь, что один из них поможет вам в вашей проблеме.

1 голос
/ 15 января 2015

Ошибка OutOfMemoryError вызвана слишком большим количеством выводимых результатов тестов. У меня была та же проблема, когда один тест показывал слишком много.

Я не знаю, происходит ли тот же эффект, когда несколько тестов хороши для себя, но выдают слишком много общего результата при совместном выполнении. Но я предполагаю, что память освобождается после каждого теста.

Анализ

Мой анализ heapdump показал, что рассматриваемый класс TeeStream, кажется, разветвляет вывод в два потока (таким образом, "T"). У меня была иерархия TeeStreams, ссылающаяся друг на друга, в то же время у меня была собственная Printer. Ваша трассировка стека также указывает на то же самое. Это означает, что каждый поступающий выход распространяется через эту иерархию и печатается несколько раз. Таким образом, размер принтеров резко увеличился, чем ниже они были. Это, конечно, очень плохо и объясняет высокое потребление памяти.

Мне кажется, это ошибка в Surefire.

Удобный обходной путь

В качестве обходного пути я уменьшил печатную продукцию моих тестов.

Более устойчивые решения

Если это не вариант для вас, вы должны настроить Surefire (в вашем .pom) для работы в раздвоенном режиме. Я уверен, что передача Xmx в качестве аргумента для увеличения размера кучи также возможна там.

0 голосов
/ 25 декабря 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...