首页 > 解决方案 > 如何在 JVM 运行调用之间持久化大型 Java 对象

问题描述

我正在处理以二进制格式存储在磁盘上的大型图形。从磁盘 (SSD) 读取图表并构建图表大约需要一个小时。一旦构建,图形永远不会改变。该图需要大约 50GB 的内存,这对服务器来说不是问题。然而,我们经常想在图上做很多实验,并且支付每小时的图加载时间会变得很昂贵。我想知道是否有任何方法可以将对象持久保存在内存中,以便 JVM 基本上可以在内存中定位对象。

我知道 JVM 在进程之间共享内存,但是我没有看到任何可以让您共享整个对象而不将对象序列化为字节的东西(考虑到昂贵的重建,这可能会很慢)。由于对象庞大(50GB),数据库解决方案似乎也很慢。因为我们没有修改对象(它实际上是静态的),所以我不关心进程之间的并发问题。

我见过的最好的想法是使用FileChannel将序列化对象映射到内存中,使用始终持久的 JVM,然后让第二个 JVM 从该 FileChannel 读取以反序列化对象。任何其他建议将不胜感激!

标签: javamemory-managementjvm

解决方案


我建议使用ChronicleMap p(我帮助设计)

这是:

  • 坚持
  • 共享
  • 堆外
  • 可以大于主存
  • 具有最小化序列化成本的选项。

例如https://github.com/OpenHFT/Chronicle-Map/blob/master/docs/CM_Tutorial.adoc

interface PostalCodeRange {
    int minCode();
    void minCode(int minCode);

    int maxCode();
    void maxCode(int maxCode);
}

ChronicleMap<Integer, PostalCodeRange> cityPostalCodes = ChronicleMap
    .of(CharSequence.class, PostalCodeRange.class)
    .averageKey("Amsterdam")
    .entries(50_000)
    .createOrRecoverPersistedTo(cityPostalCodesFile, false);

注意:这种情况下的值是堆外内存上的享元,它允许您访问字段而无需反序列化对象。


推荐阅读