2009-07-14 18 views
18

我正在研究需要与C应用程序通信的Java应用程序。 C应用程序使用共享内存和mmap进行通信,我需要Java应用程序访问相同的内存。我的第一次尝试涉及使用JNI调用从共享内存中检索数据,但是每个JNI调用的开销都会导致性能下降,所以我想要一种方法来访问Java中的内存,并在数据库上执行数据检索Java方面。访问Java内存的最佳方式是什么,类似于mmap?

的想法我是,我需要做到以下几点:

  1. 使用一个JNI调用来获取共享内存的位置,我需要重视
  2. 创建一个新的FileChannel的位置( )
  3. 使用FileChannel创建MappedByteBuffer使用地图()

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

+0

imho你不能,但我喜欢纠正 – dfa 2009-07-14 14:03:20

回答

11

看看使用ByteBuffer.allocateDirect。显然这些缓冲区可以通过JNI层传递到可以直接访问内存的本地代码。

见提示this page(下面引用)。

现在,不仅JNI代码可以发现用ByteBuffer创建的缓冲区内的本地内存空间的地址。allocateDirect()在Java端,但它可以分配自己的内存(例如malloc()),然后回调给JVM以将该内存空间包装在新的ByteBuffer对象中(JNI方法是NewDirectByteBuffer ())。

+1

这将与您在Java中获得的金属接近。不幸的是,ByteBuffer仍然需要在虚拟机边界上提取信息。看看JDK如何实现Deflator可能是有益的 - http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/Deflater.html – 2009-07-15 07:28:09

+2

我最终使用了ByteBuffers他们的工作非常出色。在JNI代码中,我创建了一个ByteBuffer并将其返回给Java代码,然后可以直接访问该内存。最后,我的Java应用程序可以读取内存并写入它。任何使用相同内存的C/C++应用程序都会立即看到写入。 – Brian 2011-04-11 14:05:51

-2

如果你可以将数据保存到在C文件,然后从Java访问该文件,这将是最好的。 AFAIK你不能以你想要使用Java的方式指向内存。丑陋的二进制数据,但可能 -

+0

这是错误的。直接字节缓冲区提供了所需的功能。 – 2012-04-05 21:58:33

0

如果你同时拥有C和Java应用程序,他们可能只是通过控制台流沟通。我会交换共享内存以获得更多的消息传递风格 - 例如TCP/IP套接字对。

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

+0

我不确定大小;可能大约800Mb,超过1Gb。不幸的是,我没有修改C应用程序的奢侈。 – Brian 2009-07-14 14:12:04

+0

创建一个包装原始C应用程序的新C应用程序。一旦你这样做,kd304的解决方案或AlbertoPL的解决方案应该是可能的。 – NamshubWriter 2009-07-14 14:18:01

+0

是否有必要在应用程序之间移动整个数据? – akarnokd 2009-07-14 14:21:35

1

我会写一个小C模块mmaps共享内存,并使用插座允许其他应用程序看到该内存(如您的Java应用程序)

0

你不能写一些本地方法的Java类,写C中的本地方法实现可以用你想要的mmap来完成。然后将其编译到本机库中,并使用LD_LIBRARY_PATH将其添加到运行时。这将使您能够在没有JNI开销的情况下使用Java进行本地C调用(我认为)。

这里有些教程: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函数。

相关问题