更改文件长度时,是否需要重新映射所有关联的 MappedByteBuffer?

2024-04-04

我有一个小而简单的存储系统,可以通过内存映射文件进行访问。由于我需要处理超过 2GB 的空间,因此我需要一个具有固定大小(如 2GB)的 MappedByteBuffer 列表(由于不同原因,我使用的空间较少)。那么一切都相对简单:一个缓冲区映射到某个空间,比如 1GB,当我需要更多时,我映射一个新的 MappedByteBuffer(文件自动增加),然后当我需要更多时,映射第三个缓冲区等。这就起作用了。

但后来我读到当我更改文件长度时可能会出现问题:

MappedByteBuffer 直接反映与其关联的磁盘文件。如果在映射生效时对文件进行结构修改,则可能会导致奇怪的行为(确切的行为取决于操作系统和文件系统) MappedByteBuffer 具有固定大小,但其映射到的文件是弹性的。具体来说,如果在映射生效时文件的大小发生变化,则部分或全部缓冲区可能变得无法访问,可能会返回未定义的数据,或者可能会引发未经检查的异常。当文件被内存映射时,要小心其他线程或外部进程如何操作文件。

我认为可能会出现问题,因为操作系统可以在文件增加时移动文件,然后 MappedByteBuffer 可能指向无效空间(或者我是否误解了这一点?)

因此,我现在不将新的 MappedByteBuffer 添加到列表中,而是执行以下操作

  1. 增加文件长度
  2. 清除缓冲区列表(扔掉旧缓冲区并希望通过垃圾收集器释放缓冲区。嗯,也许我应该通过 Cleaner.clean() 显式清理所有缓冲区?)
  3. 重新映射(用新缓冲区填充列表)

但这个过程的缺点是有时会在映射时失败

IOException: Operation not permitted
    at sun.nio.ch.FileChannelImpl.map0(Native Method)
    at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:734)

为什么?因为清除缓冲区列表没有正确释放和清理缓冲区并且不允许多个映射?我是否应该坚持旧的工作方法而忽略书中的评论?

Update

  • 在 32 位操作系统上拆分映射的优点是可以更好地找到可用空间并且不太可能出错(ref https://stackoverflow.com/a/258097/194609)
  • 将映射分割成更小的部分是一个优点,因为设置 mmap 的成本可能很高(ref https://stackoverflow.com/a/2895799/194609)
  • 这两种方法都不干净,而我的第二种方法应该可以工作,但需要取消映射(将尝试使用正常的cleaner.clean hack强制释放)。第一种方法应该适用于系统(例如ibm http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/apis/mmap.htm)我可以增加文件大小,但一般来说它不起作用,尽管我还找不到确切的原因......
  • 我担心最干净的方法是使用多个文件(每个 MappedByteBuffer 一个文件)

根本原因是我的错:我不小心过于频繁地重新映射底层文件(容量仅通过小步骤增加)。

但即使在这种极端情况下,当我重试失败的映射操作时,我最终还是能够修复 IOException(不允许操作)(+ System.gc + 5ms 睡眠 -> 这应该让 jvm 有机会取消映射缓冲区) 。现在我只看到了大量的重新映射,从而得出了最终的结论。

至少我对 mmap 有了更多的了解:它非常依赖操作系统+文件系统 - 也感谢auselen https://stackoverflow.com/users/1163019/auselen!如果您喜欢干净的解决方案,您应该按照他最初的建议为每个文件使用一个 MappedByteBuffer 。但如果您需要大空间并且操作系统文件描述符限制太低,这也可能会出现问题。

最后但并非最不重要的一点是,我强烈建议不要使用我的第一个解决方案,因为我无法找到保证(仅在 IBM 操作系统中;))在文件大小增加后使映射缓冲区保持完整。

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

更改文件长度时,是否需要重新映射所有关联的 MappedByteBuffer? 的相关文章

  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • 使用 GWT 读取非常大的本地 XML 文件

    我正在使用 GWT 构建我的第一个 Java 应用程序 它必须从一个非常大的 XML 文件中读取数据 当我尝试发送对文件中信息的请求时遇到问题 并且我不太确定它是否与文件的大小或我的语义有关 在我的程序中 我有以下内容 static fin
  • Spring Data JPA 选择不同

    我有一个情况 我需要建立一个select distinct a address from Person a 其中地址是 Person 内的地址实体 类型的查询 我正在使用规范动态构建我的 where 子句并使用findAll Specifi
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • org.hibernate.QueryException:无法解析属性:文件名

    我正在使用休眠Criteria从列中获取值filename在我的桌子上contaque recording log 但是当我得到结果时 它抛出异常 org hibernate QueryException 无法解析属性 文件名 com co
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 如何在代理后面安装 Eclipse Neon

    对于 Neon Eclipse 附带了一个安装程序 我在安装程序中找不到任何配置菜单 我的java版本是 java version java version 1 8 0 72 Java TM SE Runtime Environment b
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • 是否可以通过编程方式查找 logback 日志文件?

    自动附加日志文件以支持电子邮件会很有用 我可以以编程方式设置路径 如以编程方式设置 Logback Appender 路径 https stackoverflow com questions 3803184 setting logback
  • 使用 Guice 优化注册表

    你好 今天思考了一种优化 有一些疑问 语境 我正在使用 Guice 2 进行 Java 开发 在我的网络应用程序中 我有一个转换器注册表 可以即时转换为某种类型 转换器描述如下 public class StringToBoolean im
  • Java:如何为山区时间创建 TimeZone 对象?

    必须不禁用夏令时 嗯 在这个清单 http en wikipedia org wiki List of tz database time zones在 zoneinfo 时区名称中 有很多声称是 山地时间 找到最适合您想要的那个 然后使用它
  • 使用 Mockito 模拟某些方法,但不模拟其他方法

    有没有办法使用 Mockito 模拟类中的某些方法 而不模拟其他方法 例如 在这个 诚然是人为的 Stock我想嘲笑的班级getPrice and getQuantity 返回值 如下面的测试片段所示 但我想要getValue 执行乘法 如
  • Java实现累加器类,提供Collector

    A Collector具有三种通用类型 public interface Collector
  • HashMap 值需要不可变吗?

    我知道 HashMap 中的键需要是不可变的 或者至少确保它们的哈希码 hashCode 不会改变或与另一个具有不同状态的对象发生冲突 但是 HashMap中存储的值是否需要与上面相同 为什么或者为什么不 这个想法是能够改变值 例如在其上调
  • 返回 Java 8 中的通用函数接口

    我想写一种函数工厂 它应该是一个函数 以不同的策略作为参数调用一次 它应该返回一个函数 该函数根据参数选择其中一种策略 该参数将由谓词实现 嗯 最好看看condition3为了更好的理解 问题是 它没有编译 我认为因为编译器无法弄清楚函数式
  • JMenu 中的文本居中

    好吧 我一直在网上寻找有关此问题的帮助 但我尝试的任何方法似乎都不起作用 我想让所有菜单文本都集中在菜单按钮上 当我使用setHorizontalTextPosition JMenu CENTER 没有变化 事实上 无论我使用什么常量 菜单
  • “无法实例化活动”错误

    我的一个 Android 应用程序拥有大约 100 000 个用户 每周大约 10 次 我会通过 Google 的市场工具向我报告以下异常情况 java lang RuntimeException Unable to instantiate
  • 使用按钮作为列表的渲染器

    我想使用一个更复杂的渲染器 其中包含列表的多个组件 更准确地说 类似于this https stackoverflow com questions 10840498 java swing 1 6 textinput like firefox
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp

随机推荐