如何在JVM运行调用之间持久保存大型Java对象

时间:2018-06-27 03:32:29

标签: java memory-management jvm

我正在处理以二进制格式存储在磁盘上的大型图形。从磁盘(SSD)读取图形并构建图形大约需要一个小时。一旦构建,图就永远不会改变。该图大约需要50GB的内存,这对于服务器来说不是问题。但是,我们经常要在图形上进行大量实验,并且要花大量时间来加载图形。我想知道是否有任何方法可以将对象保留在内存中,以便JVM可以从本质上将对象定位在内存中。

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

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

1 个答案:

答案 0 :(得分:1)

我建议使用ChronicleMa 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);

注意:在这种情况下,该值是堆内存上的一个飞量,它使您可以在不反序列化对象的情况下访问字段。