内存映射文件& Java对象的透明持久性

时间:2010-06-02 07:38:36

标签: java memory-mapped-files object-persistence

全天候问候,

我希望通过内存映射文件实现Java对象的透明持久化(利用操作系统分页/交换机制)。

我的问题是:如何将Java对象移动到我的内存映射块? 另外,如何强制新对象实例驻留在这些块中?

众所周知,内存映射块可以看作是一个字节数组,我在这里真正要问的是如何将Java对象的地址空间与这样的数组重叠?因此,我们仍然可以通过对象操作数据,而操作系统透明地处理持久性(写脏页)。

如果Java不允许我这样做,那么什么是跨平台& amp;垃圾收集OO语言你建议我使用吗?

提前谢谢大家。

3 个答案:

答案 0 :(得分:3)

这是不可能的。运行时不允许这样做有几个很好的理由。

  • 对象的内存布局是JVM内部的一部分。每个JVM都可以自己决定如何布局对象。此布局可以更改版本。当您将对象内存映射到文件时,您将遇到麻烦。对象布局发生变化后会发生什么?崩溃,更新文件,做魔术?最后,内存映射对象到文件需要指定一个固定的对象布局。
  • 如果添加/删除字段会怎样?然后对象布局肯定已经改变了。您无法使用旧内存布局对文件进行内存映射。
  • 对象还有其他信息,例如用于虚拟函数调用的VTable,用于锁定状态的字段等。您是否也想要映射它们?可能不是,因为那是内部运行时状态。所以你需要总是忽略几个字节或分裂对象。这会使内存布局变得非常复杂。
  • 垃圾收集器通过移动对象来压缩内存以最大限度地减少碎片。因此,需要有一个物体的“固定”机制。 (出于互为原因,这在.NET中是可能的)
  • 垃圾收集器世代相传。如果首先在年轻一代分配的对象。随着它的存在,它被转移到其他一代。内存映射对象需要例外。

由于所有这些原因,您无法对Java / .NET对象进行内存映射。支持这样的功能会使JVM / CLR变得极其复杂。

JVM / CLR仍然允许您将内存映射文件作为类似数组的抽象访问,您可以在其中写入/读取字节。除此之外,您还可以实现持久性机制。从简单的序列化到复杂的数据库。 有些对象数据库非常接近,可以提供透明的持久性。然后,对象的行为类似于持久性数据结构/内存映射对象。

答案 1 :(得分:3)

您可以使用自己的Java VM并添加此功能。当然,您编写的代码不是Java,而是使用VM实现的语言。很久以前,Gemstone将这种方法用于其对象数据库引擎。

今天的对象数据库(我工作一个。)不这样做。增强字节码以跟踪字段访问并使用反射或注入方法将对象转换为某种序列化形式更为直接。这表现得相当不错。如果要支持查询,则必须使用单个字段值来索引它们。

对于我们来说,为我们想要运行的所有平台维护VM是不可行的。我们也无法说服认真的客户将他们的整个(银行)应用程序放在我们定制的VM上。

如果您对生成基于Java VM的解决方案非常感兴趣: 曾经有一个有趣的Java研究项目,用于称为“森林”的正交透明持久性。您或许可以找到旧论文甚至是源代码。

如果您正在寻找另一种语言直接从内存中获取“对象”:C ++将允许您这样做。有一些用C ++编写的旧对象数据库使用这种方法。 ...但是,嘿,这是疯狂的东西,使用页面错误来加载对象。这些对象数据库产生了坏图像。我希望我们很快就会再次扭转局面。

答案 2 :(得分:1)

你不能。

Java,按设计,强制实施类型安全和参照完整性。也就是说,如果我有一个引用类型为T的字段,我知道它指向一个T的实例(禁止由类型擦除引入的堆污染)。这与诸如C ++之类的“不安全”语言形成对比,其中引用很可能指向无效位置,其中该引用可能导致“内存损坏”。

如果Java允许将byte []视为Object,则无法保证此类参照完整性。