Java map / nio / NFS 问题导致虚拟机故障:“编译的 Java 代码中最近的不安全内存访问操作发生故障”

2024-01-02

我已经为特定的二进制格式编写了一个解析器类(nfdump http://nfdump.sf.net/如果有人感兴趣)它使用 java.nio映射字节缓冲区 http://java.sun.com/j2se/1.4.2/docs/api/java/nio/MappedByteBuffer.html读取每个几 GB 的文件。二进制格式只是一系列标头和大部分固定大小的二进制记录,通过调用 nextRecord() 将其提供给被调用者,该状态机会推送状态机,完成后返回 null。它表现良好。它可以在开发机器上运行。

在我的生产主机上,它可以运行几分钟或几个小时,但似乎总是抛出“java.lang.InternalError:编译的 Java 代码中最近不安全的内存访问操作中发生故障”,指着 Map.getInt 之一、getShort方法,即map中的读操作。

设置地图的无争议(?)代码是这样的:

    /** Set up the map from the given filename and position */
    protected void open() throws IOException {
            // Set up buffer, is this all the flexibility we'll need?
            channel = new FileInputStream(file).getChannel();    
            MappedByteBuffer map1 = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
            map1.load(); // we want the whole thing, plus seems to reduce frequency of crashes?
            map = map1;
            // assumes the host  writing the files is little-endian (x86), ought to be configurable
            map.order(java.nio.ByteOrder.LITTLE_ENDIAN);
            map.position(position);
    }

然后我使用各种 map.get* 方法来读取短整型、整数、长整型和其他字节序列,然后到达文件末尾并关闭映射。

我从未见过我的开发主机上抛出异常。但我的生产主机和开发主机之间的显着区别在于,在前者上,我通过 NFS 读取这些文件的序列(最终可能为 6-8TB,仍在增长)。在我的开发计算机上,我在本地选择了较小的这些文件 (60GB),但当它在生产主机上崩溃时,通常会在它达到 60GB 数据之前就发生。

两台机器都运行 java 1.6.0_20-b02,尽管生产主机运行 Debian/lenny,但开发主机运行 Ubuntu/karmic。我不相信这会产生任何影响。两台机器都有 16GB RAM,并且使用相同的 java 堆设置运行。

我认为,如果我的代码中存在错误,那么 JVM 中的错误就足够多,不会引发适当的异常!但我认为这只是由于 NFS 和 mmap 之间的交互而导致的一个特定的 JVM 实现错误,可能是重复出现的6244515 https://bugs.java.com/bugdatabase/view_bug?bug_id=6244515这是官方固定的。

我已经尝试添加“加载”调用来强制 MappedByteBuffer 将其内容加载到 RAM 中 - 这似乎延迟了我所做的一次测试运行中的错误,但并没有阻止它。也可能是巧合,这是它坠毁前所经历的最长时间!

如果您已经读到这里并且以前使用 java.nio 做过这种事情,您的直觉会是什么?现在我的目标是在没有 nio 的情况下重写它:)


我会重写它而不使用mapped蔚来。如果您正在处理多个文件,则会出现一个问题,即映射的内存永远不会被释放,因此您将耗尽虚拟内存:注意,这不一定只是与垃圾收集器交互的 OutOfMemoryError,它可能是一个无法分配新的映射缓冲区。我会使用 FileChannel。

话虽如此,对 NFS 文件的大规模操作总是会出现极大的问题。最好重新设计系统,以便每个文件都由其本地 CPU 读取。通过这种方式,您还将获得巨大的速度提升,远远超过不使用映射缓冲区所损失的 20%。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java map / nio / NFS 问题导致虚拟机故障:“编译的 Java 代码中最近的不安全内存访问操作发生故障” 的相关文章

随机推荐