内存映射文件和内存映射文件Java 对象的透明持久化

发布于 2024-09-03 15:56:39 字数 319 浏览 7 评论 0原文

大家好,

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

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

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

如果Java不允许我这样做,那么跨平台和跨平台是什么?你会建议我使用垃圾收集的面向对象语言吗?

预先感谢大家。

Greeting All,

I want to achieve transparent persistence of Java objects through memory-mapped files (utilize the OS paging/swapping mechanism).

My problem is: how can I move a Java object to my memory-mapped block ?
Plus, how can I force a new object instance to reside in such blocks ?

As you all know, a memory-mapped block can be seen as a byte array, and what I am really asking here is how to overlap the address space of Java objects with the one of such arrays ? So that we can still manipulate the data via objects while OS handles persistence transparently (writes dirty pages).

If Java does not allow me for this, what cross-platform & garbage-collecting OO language would you advise me to use ?

Thank you all in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鸠书 2024-09-10 15:56:39

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

今天的对象数据库(我正在开发一个)并不以这种方式做事。增强字节码以跟踪字段访问并使用反射或注入方法将对象转换为某种序列化形式要简单得多。这表现相当不错。如果您想支持查询,则无论如何都必须使用各个字段值来对其进行索引。

对于我们来说,为我们想要运行的所有平台维护一个虚拟机是不可能的。我们也不可能说服认真的客户将他们的整个(银行)应用程序依赖于我们定制的虚拟机。

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

如果您正在寻找一种不同的语言来直接从内存中获取“对象”:C++ 可以让您做到这一点。有一些用 C++ 编写的旧对象数据库使用这种方法。
...但是,嘿,这太疯狂了,使用页面错误来加载对象。这些对象数据库产生了不好的形象。我希望我们很快就能扭转局面。

The only way you can do this is by using your own Java VM and adding this functionality. Of course the code that you would write would not be in Java but in the language the VM is implemented in. Quite some time ago Gemstone used this approach for their object database engine.

Todays object databases (I work on one.) don't do things this way. It's much more straightforward to enhance bytecode to track field access and to use reflection or injected methods to turn objects into some kind of serialized form. This performs quite good. If you want to support querying, you have to work with individual field values anyway to index them.

For us it would just not be doable to maintain a VM for all the platforms that we want to run on. We also couldn't possibly convince serious customers to rely their entire (banking) application on a VM that we customize.

If you are seriously interested in producing a solution based on a Java VM:
There used to be an interesting Java research project for orthogonal transparent persistence called "Forest". You may be able to find old papers or even source code.

If you are looking for a different language to take "objects" from memory directly: C++ will let you do that. There are some old object databases written in C++ that use this approach.
...but hey, that's crazy stuff, using page faults to load objects. These kind of object databases produced the bad image. I hope we will turn it around again soon.

吻泪 2024-09-10 15:56:39

据我所知这是不可能的。运行时不允许这样做有几个充分的理由。

  • 对象的内存布局是 JVM 内部结构的一部分。每个 JVM 都可以自己决定如何布局对象。此布局可能会随着版本的不同而改变。当您将对象内存映射到文件时,您会遇到麻烦。当对象布局发生变化时会发生什么?崩溃,更新文件,施展魔法?最后,将对象内存映射到文件需要指定固定的对象布局。
  • 如果添加/删除字段会发生什么?那么对象布局肯定已经改变了。您无法使用旧内存布局对文件进行内存映射。
  • 对象还具有附加信息,例如用于虚拟函数调用的 VTable、用于锁定状态的字段等。您也想要映射它们吗?可能不是,因为那是内部运行时状态。因此,您需要始终忽略一些字节或分割对象。这将使内存布局变得极其复杂。
  • 垃圾收集器通过移动对象来压缩内存以最大限度地减少碎片。因此,需要有一个对象的“固定”机制。 (出于互操作原因,这在 .NET 中是可能的)
  • 垃圾收集器分代工作。一个对象如果首先分配在年轻代上。当它幸存下来时,它就会被转移到另一代。内存映射对象需要异常。

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

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

This is afaik not possible. And there are several good reasons why the runtime doesn't allow this.

  • The memory layout of your object is part of the JVM internals. Each JVM can make it own decisions how to layout objects. This layout can change over releases. When you memory-map a object to a file, you would run into trouble. What happens when the object-layout has changed? Crash, update the file, do magic? In the end memory-mapping objects to files would require to specify a fixed object-layout.
  • What happens if you add/remove a field? Then the object-layout has changed for sure. You cannot memory-map a file with the old memory-layout.
  • A object has also additional information, like the VTable for virtual function-calls, fields for lock-states etc. Do you want the map them also? Probably not, because thats internal runtime-state. So you would require to alway ignore a few bytes or split-up objects. That would make the memory-layout extremely complex.
  • The garbage collector compacts the memory to minimize fragmentation by moving objects around. Therefore there needs to be a 'fixation'-mechanism for objects. (that's possible in .NET, for interop-reasons)
  • The garbage collector works in generations. A object if first allocated on a young generation. As it survives it is moved to other generation. A memory-mapped object would require an exception.

For all these reasons you cannot memory-map Java/.NET-objects. Supporting such a feature would make the JVM/CLR extremely complex.

The JVM/CLR still give you access to Memory-Mapped files as an array-like abstraction, where you can write/read bytes. On top of this you can implement your persistence-mechanism. From simple serialisation to complex databases.
There are object-databases which come quite close to provide transparent persistence. Then objects behave like persistent datastructures / memory-mapped objects.

乖乖公主 2024-09-10 15:56:39

你不能。

Java 在设计上强制执行类型安全和引用完整性。也就是说,如果我有一个引用类型 T 的字段,我知道它指向 T 的一个实例。(除非类型擦除引入堆污染)。这与 C++ 等“不安全”语言形成鲜明对比,在 C++ 中,引用很可能指向无效位置,而该引用可能会导致“内存损坏”。

如果 Java 允许将 byte[] 视为 Object,则它无法保证这种引用完整性。

You can't.

Java, by design, enforces type safety and referential integrity. That is, if I have a field of reference type T, I know it points to a instance of T. (Barring heap-pollution introduced by type erasure). This is in contrast to "unsafe" languages such a C++ where it is quite possible for a reference to point to an invalid location, where that reference can cause "memory corruption".

If Java allowed to treat a byte[] as Object, it could not guarantee such referential integrity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文