【问题标题】:What is the best way to access memory in Java, similar to mmap?在 Java 中访问内存的最佳方式是什么,类似于 mmap?
【发布时间】:2010-11-10 15:57:11
【问题描述】:

我正在开发一个需要与 C 应用程序通信的 Java 应用程序。 C 应用程序使用共享内存和 mmap 进行通信,我需要 Java 应用程序能够访问相同的内存。

我的第一次尝试涉及使用 JNI 调用从共享内存中检索数据,但是每个 JNI 调用的开销都会影响性能,所以我想要一种方法来访问 Java 中的内存并在Java 方面。

我的想法是我需要执行以下操作:

  1. 使用一个 JNI 调用来获取我需要附加到的共享内存位置的位置
  2. 创建一个新的 FileChannel()
  3. 使用该 FileChannel 通过 map() 创建一个 MappedByteBuffer

这是最好的方法吗?另外,我不确定如何实际创建 FileChannel 以指向正确的内存位置。

【问题讨论】:

  • 恕我直言,你不能,但我喜欢被纠正

标签: java memory


【解决方案1】:

考虑使用ByteBuffer.allocateDirect。显然,这些缓冲区可以通过 JNI 层传递给可以直接访问内存的本机代码。

有关提示,请参阅this page(以下引用)。

现在,JNI 代码不仅可以发现在 Java 端使用 ByteBuffer.allocateDirect() 创建的缓冲区内的本机内存空间地址,而且可以分配自己的内存(例如使用 malloc())然后回调 JVM 以将该内存空间包装在一个新的 ByteBuffer 对象中(执行此操作的 JNI 方法是 NewDirectByteBuffer())。

【讨论】:

  • 这将尽可能接近 Java 中的金属。不幸的是,ByteBuffer 仍然需要跨 VM 边界提取信息。看看 JDK 是如何实现 Deflator 的可能会有启发性 - java.sun.com/j2se/1.4.2/docs/api/java/util/zip/Deflater.html
  • 我最终使用了 ByteBuffers,它们的效果非常好。在 JNI 代码中,我创建了一个 ByteBuffer 并将其返回给 Java 代码,然后它可以直接访问该内存。最后,我的 Java 应用程序可以读取和写入内存。任何使用相同内存的 C/C++ 应用程序都可以立即看到写入。
【解决方案2】:

我会编写一个小型 C 模块来映射共享内存并使用套接字来允许另一个应用程序查看该内存(例如您的 Java 应用程序)

【讨论】:

    【解决方案3】:

    如果您同时拥有 C 和 Java 应用程序,它们可以只通过控制台流进行通信 - 对于二进制数据来说很难看,但可能。我会将共享内存换成更多的消息传递方式——例如TCP/IP 套接字对。

    顺便说一句,传递什么样的数据,有多大?

    【讨论】:

    • 我不太确定尺寸;可能是大约 800Mb 到超过 Gb。不幸的是,我没有修改 C 应用程序的奢侈。
    • 创建一个新的 C 应用程序来包装原始 C 应用程序。一旦你这样做了,kd304 的解决方案或 AlbertoPL 的解决方案都应该是可能的。
    • 是否总是需要在应用程序之间移动整个数据?
    • 数据根本不需要移动,我只需要能够从C应用程序使用的共享内存中读取即可。
    【解决方案4】:

    难道你不能用一些本地方法编写一个Java 类,用C 编写本地方法实现来用mmap 做你想做的事。然后将其编译为本机库并使用 LD_LIBRARY_PATH 将其添加到您的运行时。这将使您能够在 Java 中进行本地 C 调用,而不会产生 JNI 开销(我认为)。

    这里有一些教程:link

    例如,您将编写一个 Java 类,例如:

    JMMap.java
    
    public class JMMap {
        public native void write(...)
    }
    

    然后对类文件运行 javah 以生成如下内容:

    JMMap.h
    
    JNIEXPORT void JNICALL Java_JMMap_write(JNIEnv *, jobject);
    

    在 .c 文件中实现这一点。将其编译到库中。将其添加到 LD 路径,然后调用 Java 函数即可。

    【讨论】:

      【解决方案5】:

      如果您可以将数据保存到 C 中的文件中,然后从 Java 中访问该文件,那将是最好的。 AFAIK,您不能以您希望使用 Java 的方式指向内存。

      【讨论】:

      • 这是错误的。直接字节缓冲区提供了所需的功能。
      猜你喜欢
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2020-04-10
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多