从JNI中编组数据的最快方法是什么

时间:2012-01-23 21:56:43

标签: java android-ndk java-native-interface

假设我有一个包含许多数据字段(> 15)的C数据结构:

struct MyData
{
   int x;
   float y;
   ...
}

在Java中,我可以将指向MyData的指针存储为long,并通过JNI调用访问C数据结构的成员:

long mydata_p = MyDataJNI.alloc();

int x = MyDataJNI.getX( mydata_p );
float y = MyDataJNI.getY( mydata_p );
...

然而,对这些功能的调用非常昂贵(相当于C函数调用的成本的10倍-100倍)。即使实现getX,getY,...也是如此简单:

return ((MyData*)())->x

Q1:为什么JNI这么贵?除了调用函数指针之外还会发生什么? (作为参考,我正在研究Android中的JNI调用。)

Q2:在Java层提供C结构的所有元素的最快速度是什么?

2 个答案:

答案 0 :(得分:1)

您可以让它在Java对象中返回结果,而不是将本机调用的结果存储在外部管理的指针中。

最简单的方法是将C结构直接memcpy到byte[],然后在Java端,将该数组包装在ByteBuffer中并使用getInt(),{{{ 1}}等等。

您还可以返回构造的Java对象数组,以反映您的结构,但代码将是一个令人难以置信的混乱,有点类似于通过显式内存管理反射构建所有内容。

答案 1 :(得分:1)

您希望通过一次JNI调用移动所有数据。您可以将其复制到原始字节数组(然后使用ByteArrayOutputStream和DataOutputStream的某种组合从中提取Java原语),或者使用直接NIO ByteBuffer(ByteBuffer.allocateDirect),如果您需要将数据移回更有意义来回。直接ByteBuffer是专门为在VM和本机代码之间共享内存而设计和优化的。