-XX:+ExitOnOutOfMemoryError 在“java.lang.OutOfMemoryError: Direct buffer memory”上被忽略

den*_*lah 6 java nio

如果OutOfMemoryError是由分配直接字节缓冲区引起的,-XX:+ExitOnOutOfMemoryError则忽略JVM 标志。

检查 Oracle JDK 和 OpenJDK Java 版本“1.8.0_144” Java(TM) SE 运行时环境(构建 1.8.0_144-b01)Java HotSpot(TM)64 位服务器 VM(构建 25.144-b01,混合模式)

操作系统:Ubuntu 16.04

重现运行以下代码

package com.company;
import java.nio.ByteBuffer;
public class Main {

    public static void main(String[] args) {
        // This should guarantee to throw:            
        try {
            ByteBuffer bb = ByteBuffer.allocateDirect(10485760*2);
            System.out.println("OOME not triggered");
        } catch (OutOfMemoryError err) {                
            System.out.println("OOME didn't terminate JVM!");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

虚拟机参数: -XX:MaxDirectMemorySize=10485760 -XX:+ExitOnOutOfMemoryError

程序输出“OOME 没有终止 JVM!” 并以退出代码 0 终止。我预计它会崩溃并返回大于 0 的退出代码。当OutOfMemory由于堆空间不足而抛出时,它以这种方式工作。

如果您使用 jvm args 运行以下代码,-Xmx10485760 -XX:+ExitOnOutOfMemoryError则 jvm 进程将崩溃并显示退出代码 3:

try {        
    byte[] b = new byte[10485760*2];
    System.out.println("OOME not triggered");
} catch (OutOfMemoryError err) {
    System.out.println("OOME didn't terminate JVM!");
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出将是: Terminating due to java.lang.OutOfMemoryError: Java heap space 这是预期的行为,但没有在第一个示例中重现。

如何ExitOnOutOfMemoryError选择适用于这种情况?也许有更新的 JDK 或替代的 JDK 实现没有这样的错误?

我在 druid.io 有这个问题。如果实时索引任务遇到

java.lang.OutOfMemoryError: Direct buffer memory
Run Code Online (Sandbox Code Playgroud)

它挂起并且不会终止。

Hal*_*Hal 5

根据 Java 问题跟踪器上的讨论,ExitOnOutOfMemoryError仅旨在涵盖 JVM 本身引发的 OutOfMemory 错误。NIO 缓冲区是从本机代码分配的,因此与它们相关的 OOM 错误也会从本机代码抛出,因此不幸的是,这似乎是预期的行为。

\n\n