java - java 中的 Fuse 文件系统 - JVM 错误双重释放或损坏

标签 java fuse jnr

我正在使用 jnr-fuse 库 ( https://github.com/SerCeMan/jnr-fuse ) 在 java 中编写 Fuse 文件系统,该库在内部使用 JNR 进行 native 访问。

文件系统充当 Amazon S3 存储桶的前端,基本上使用户能够将其存储桶作为普通存储设备安装。

在重新设计我的读取方法时,我遇到了以下 JVM 错误:

*** Error in `/usr/local/bin/jdk1.8.0_65/bin/java': double free or corruption (!prev): 0x00007f3758953d80 ***

尝试将文件从熔断文件系统复制到本地 FS 时总是会发生错误,通常是在第二次调用 read 方法时(对于第二个 128kByte 数据 block )

 cp /tmp/fusetest/benchmark/benchmarkFile.large /tmp

有问题的读取方法是:

public int read(String path, Pointer buf, @size_t long size, @off_t long offset, FuseFileInfo fi) {
    LOGGER.debug("Reading file {}, offset = {}, read length = {}", path, offset, size);
    S3fsNodeInfo nodeInfo;
    try {
        nodeInfo = this.dbHelper.getNodeInfo(S3fsPath.fromUnixPath(path));
    } catch (FileNotFoundException ex) {
        LOGGER.error("Read called on non-existing node: {}", path);
        return -ErrorCodes.ENOENT();
    }
    try {
        // *** important part start
        InputStream is = this.s3Helper.getInputStream(nodeInfo.getPath(), offset, size);
        byte[] data = new byte[is.available()];
        int numRead = is.read(data, 0, (int) size);
        LOGGER.debug("Got {} bytes from stream, putting to buffer", numRead);
        buf.put(offset, data, 0, numRead);
        return numRead;
        // *** important part end
    } catch (IOException ex) {
        LOGGER.error("Error while reading file {}", path, ex);
        return -ErrorCodes.EIO();
    }
}

使用的输入流实际上是缓冲区上的 ByteArrayInputStream,我用它来减少与 S3 的 http 通信。 我现在在单线程模式下运行熔断以避免任何并发相关的问题。

有趣的是,我已经有了一个没有进行任何内部缓存的工作版本,但其他方面与此处所示的完全相同。

不幸的是,我不太了解 JVM 内部结构,所以我不确定如何深入了解这个问题 - 正常的调试不会产生任何结果,因为实际错误似乎发生在 C 端。

这是上述命令触发的读取操作的完整控制台输出:

2016-02-29 02:08:45,652 DEBUG s3fs.fs.CacheEnabledS3fs [main] - Reading file /benchmark/benchmarkFile.large, offset = 0, read length = 131072
unique: 7, opcode: READ (15), nodeid: 3, insize: 80, pid: 8297
read[0] 131072 bytes from 0 flags: 0x8000
2016-02-29 02:08:46,024 DEBUG s3fs.fs.CachedS3Helper [main] - Getting data from cache - path = /benchmark/benchmarkFile.large, offset = 0, length = 131072
2016-02-29 02:08:46,025 DEBUG s3fs.fs.CachedS3Helper [main] - Path /benchmark/benchmarkFile.large not yet in cache, add it
2016-02-29 02:08:57,178 DEBUG s3fs.fs.CachedS3Helper [main] - Path /benchmark/benchmarkFile.large found in cache!
   read[0] 131072 bytes from 0
   unique: 7, success, outsize: 131088
2016-02-29 02:08:57,179 DEBUG s3fs.fs.CachedS3Helper [main] - Starting actual cache read for path /benchmark/benchmarkFile.large
2016-02-29 02:08:57,179 DEBUG s3fs.fs.CachedS3Helper [main] - Reading data from cache block 0, blockOffset = 0, length = 131072
2016-02-29 02:08:57,179 DEBUG s3fs.fs.CacheEnabledS3fs [main] - Got 131072 bytes from stream, putting to buffer
2016-02-29 02:08:57,180 DEBUG s3fs.fs.CacheEnabledS3fs [main] - Reading file /benchmark/benchmarkFile.large, offset = 131072, read length = 131072
unique: 8, opcode: READ (15), nodeid: 3, insize: 80, pid: 8297
read[0] 131072 bytes from 131072 flags: 0x8000
2016-02-29 02:08:57,570 DEBUG s3fs.fs.CachedS3Helper [main] - Getting data from cache - path = /benchmark/benchmarkFile.large, offset = 131072, length = 131072
2016-02-29 02:08:57,570 DEBUG s3fs.fs.CachedS3Helper [main] - Path /benchmark/benchmarkFile.large found in cache!
2016-02-29 02:08:57,570 DEBUG s3fs.fs.CachedS3Helper [main] - Starting actual cache read for path /benchmark/benchmarkFile.large
2016-02-29 02:08:57,571 DEBUG s3fs.fs.CachedS3Helper [main] - Reading data from cache block 0, blockOffset = 131072, length = 131072
2016-02-29 02:08:57,571 DEBUG s3fs.fs.CacheEnabledS3fs [main] - Got 131072 bytes from stream, putting to buffer
   read[0] 131072 bytes from 131072
   unique: 8, success, outsize: 131088
*** Error in `/usr/local/bin/jdk1.8.0_65/bin/java': double free or corruption (!prev): 0x00007fcaa8b30c80 ***

最佳答案

好吧,这确实是一个愚蠢的错误......

buf.put(offset, data, 0, numRead);

当然是无意义的 - 传递的 offset 参数意味着正在读取的文件中的偏移量,而不是缓冲区中的偏移量。

适用于:

buf.put(0, data, 0, numRead);

这个相当神秘的错误只是意味着我正在尝试写入在这种情况下我无权写入的内存位置。 很好奇为什么这是这个错误消息而不是我通常期望的段错误..

关于java - java 中的 Fuse 文件系统 - JVM 错误双重释放或损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35690447/

相关文章:

java - 如何格式化电子邮件中的字符串以便 Outlook 打印换行符?

java - 尽管实现了 "getColumnClass",但 JTable 显示 true/false 而不是 CheckBox

hadoop - 挂载Hadoop文件系统

java - 调用 c 函数复制结构后 JNR-FFI 崩溃

java - 如何将 native 内存复制到 DirectByteBuffer

java - jEdit StandaloneTextArea 的自定义配色方案?

java - 使用 DOM 在开始标签和结束标签之间添加属性,而不是在一个标签之间添加属性

c - 为什么我不能设置大于 2^32 的 time_t?

python - 使用 FUSE 在 python 中创建一个临时文件

java - 如何指定像 python ctypes 那样的 JNR 指针