当前位置:  开发笔记 > 编程语言 > 正文

导致VM故障的Java map/nio/NFS问题:"在编译的Java代码中最近的不安全内存访问操作中发生了故障"

如何解决《导致VM故障的Javamap/nio/NFS问题:"在编译的Java代码中最近的不安全内存访问操作中发生了故障"》经验,为你挑选了0个好方法。

我已经为特定的二进制格式编写了一个解析器类(nfdump,如果有人感兴趣的话),它使用java.nio的MappedByteBuffer来读取每个几GB的文件.二进制格式只是一系列标题和大多数固定大小的二进制记录,它们通过调用nextRecord()输出到被调用者,后者推送状态机,在完成时返回null.它表现很好.它适用于开发机器.

在我的生产主机上,它可以运行几分钟或几小时,但似乎总是抛出"java.lang.InternalError:在编译的Java代码中最近的一个不安全的内存访问操作中发生了一个错误",指法其中一个Map.getInt ,getShort方法,即地图中的读取操作.

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

    /** 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*方法来读取short,int,long和其他字节序列,然后点击文件末尾并关闭地图.

我从来没有见过我的开发主机上抛出的异常.但是我的生产主机和开发之间的重要区别在于前者,我正在通过NFS读取这些文件的序列(最终可能是6-8TB,仍然在增长).在我的开发机器上,我在本地选择了较少的这些文件(60GB),但是当它在生产主机上爆炸时,它通常会在它达到60GB的数据之前.

两台机器都运行java 1.6.0_20-b02,虽然生产主机运行的是Debian/lenny,开发主机是Ubuntu/karmic.我不相信会有任何不同.两台机器都有16GB RAM,并且使用相同的Java堆设置运行.

我认为,如果我的代码中存在错误,JVM中有足够的错误不会给我一个正确的异常!但我认为由于NFS和mmap之间的交互,这只是一个特定的JVM实现错误,可能是6244515的重复,这是正式修复的.

我已经尝试添加一个"加载"调用来强制MappedByteBuffer将其内容加载到RAM中 - 这似乎延迟了我已完成的一次测试运行中的错误,但并未阻止它.或者它可能是巧合,它是崩溃前最长的!

如果你已经读过这篇文章并且以前用java.nio做过这种事情,你的直觉是什么?现在我的是没有nio重写它:)

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有