当测试将大量日志消息打印到 System.out 时,Jenkins 会出现堆溢出 (OutOfMemoryError)

Gen*_*nry 2 java jenkins

我正在使用 Jenkins 来运行一些系统测试。这些测试将 18-20 MB 的打印输出写入标准输出。Jenkins 作业配置为以 2048 MB 最大堆大小运行。奇怪的是,当这些打印输出打开时,jenkins 会出现 OutOfMemoryError (堆空间不足)。

肯定是打印输出导致了问题。没有他们,一切都正常。让我烦恼的是,20 MB 的文本如何导致整个过程内存不足。

我已经将堆大小从 1 GB 增加到 2 GB,但没有任何结果。如果没有打印,在 1GB 最大堆大小上,所有测试都可以正常工作。

这里有一个例外:

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)
    ...
Run Code Online (Sandbox Code Playgroud)

有谁知道 Jenkins 的某种配置,即大量打印到 System.out (其中 20 MB)不会导致 OutOfMemory 发生?

澄清:我不想调试 Jenkins,我不是 Jenkins 开发人员。我使用 Jenkins 在我的应用程序上使用 JUnit 作为 CI 来运行系统测试。

小智 5

尝试使用“-XX:+HeapDumpOnOutOfMemoryError”JVM参数启动jenkins,这应该会给你一个转储文件,以便在出现内存不足异常时进行分析。

编辑 -

我想我可能有东西给你。
首先,surefire插件默认会fork一个新的JVM来运行测试,并且这个JVM不会继承maven JVM的JVM属性,即如果您将maven进程设置为具有2048MB Max Heap,则不会将其设置为由 Surefire 插件分叉的 JVM。
因此,要设置分叉 JVM 的 JVM 参数,请使用 Surefire 插件的“argLine”属性。这样您就可以为分叉 JVM 而不是 Maven JVM 设置最大堆。

其次,看起来 Surefire 插件会重定向 stdout/stderr 并将写入这两个流的内容保留在内存中,这就是您可能会耗尽内存的原因。
因此,您还可以尝试将 'redirectTestOutputToFile' 属性设置为 'true',这样所有 sdtout 都会转到文件,可能会避免将流内容存储在内存中,
或者尝试设置 forkmode='always',这样就可以了每个测试类 fork 一个 JVM,从而防止内存消耗在一个又一个测试中堆积。

希望其中之一能帮助您解决问题。