在JVM外分配内存并在JVM内使用

13

能否创建一个持久性内存对象,使其位于JVM内存之外,并可以在JVM内部用作对象,以便在JVM重新启动后仍然存活?

具体的想法是,在JVM之外分配内存,然后使用JNI接口访问该内存并将某些Java数组与其关联。

是否有人尝试过这样的黑客行为?任何平台相关性都可以。

例如,这有助于在JVM进程重新启动期间执行内存数据库加载的优化。


你肯定无法将它分配给一个真正的Java数组,比如float[]之类的。但是你可以在Java中使用外部分配的内存,通过使用JNI返回作为直接ByteBuffer创建的内存,并使用NewDirectByteBuffer。我不确定如何实现JVM重启后的生存能力(并且目前无法明智地尝试它),但是如果这部分可以解决,直接的ByteBuffer可能是正确的方法。 - Marco13
2个回答

14

是的,即使没有使用JNI,这也完全可以实现。

思路是使用由MappedByteBuffer支持的“文件”,放置在tmpfs文件系统上。例如,在Linux系统上,您可以使用/dev/shm(或/run/shm)挂载点进行操作。

这样的MappedByteBuffer性能与其他直接字节缓冲区相同,但它会在JVM重启后仍然存在,也就是说,您可以在新的JVM中重新映射这个“文件”。(我用引号括起来写“文件”,因为对于应用程序来说它看起来像是一个普通的文件,但实际上它是一个驻留在RAM中的共享内存区域)。我们在生产环境的内存缓存中积极使用这种技术。


问题中没有提到Linux...所以这是特定于平台的 - 或者在Windows上有类似的东西吗? - Marco13
@Marco13 在Windows上,您可以使用RAM磁盘,但我认为您需要安装它。 - Peter Lawrey

6
你可以自己使用MappedByteBuffer,或者使用建立在MappedByteBuffer之上的数据结构,以便在重新启动时可用,甚至在JVM之间共享。 Chronicle-Map具有以ConcurrentMap为模型的键值存储。例如:Map<String, YourType> Chronicle-Queue是您系统中每个事件的日志,您可以实时消费。
这两个都是开源和免费的,并且可以帮助您节省存储和检索对象的工作。
注意:由于这些是离堆和持久化的,它们可以达到TB级别的大小,而不影响GC暂停时间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接