假设我有一个包含许多数据字段(> 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结构的所有元素的最快速度是什么?
答案 0 :(得分:1)
您可以让它在Java对象中返回结果,而不是将本机调用的结果存储在外部管理的指针中。
最简单的方法是将C结构直接memcpy到byte[]
,然后在Java端,将该数组包装在ByteBuffer
中并使用getInt()
,{{{ 1}}等等。
您还可以返回构造的Java对象数组,以反映您的结构,但代码将是一个令人难以置信的混乱,有点类似于通过显式内存管理反射构建所有内容。
答案 1 :(得分:1)
您希望通过一次JNI调用移动所有数据。您可以将其复制到原始字节数组(然后使用ByteArrayOutputStream和DataOutputStream的某种组合从中提取Java原语),或者使用直接NIO ByteBuffer(ByteBuffer.allocateDirect),如果您需要将数据移回更有意义来回。直接ByteBuffer是专门为在VM和本机代码之间共享内存而设计和优化的。