GetIntArrayElements
有一个可选的引用参数isCopy
。当虚拟机为您使用数据副本时,此参数将设置为JNI_TRUE
。这个想法是,不同的虚拟机实现可能有不同的数组内存表示,也是与C期望的内存布局不兼容的。
通常,在Java和本机代码之间共享内存的最快方式是使用直接ByteBuffer
(使用allocateDirect
创建的那些)。这些缓冲区使用可从C/C++直接使用的底层内存块。
在Java中创建一个缓冲区,并用一些数据填充它:
public static void main(String[] args) {
byte[] ba = "Hello Wolrd!".getBytes(StandardCharsets.US_ASCII);
ByteBuffer bb = ByteBuffer.allocateDirect(ba.length + 1); // for terminator
bb.put(ba);
callCPP(bb);
}
private static native void callCPP(ByteBuffer bytes);
再从C/C++,你可以用GetDirectBufferAddress
(这是C++)得到字节的基本块的地址:
JNIEXPORT void JNICALL Java_Main_callCPP(JNIEnv *env, jclass, jobject buff) {
const char* str = (char*) env->GetDirectBufferAddress(buff);
printf(str); // Hello World!
}
使用ByteBuffer
的缺点是不存在的数据抽象,像一类字段具有特定的类型,在字节缓冲器中的位置不。
您可以传递一个直接的字节缓冲区,它或多或少地像一个指针。但是我怀疑你会从使用JNI中获得很多收益。 Oracle的JVM有一个JIT,它发出高度优化的本机代码。如果有任何性能优势,它可能不会摊销互操作成本。当你有一些你可以在C中完成的东西时,JNI是非常有用的,但是在Java中不能完成,例如OpenGL。 –
感谢您的评论! 你介意共享更多关于字节缓冲区的信息吗? (一个链接就足够了) 此外,你的评论意味着'GetIntArrayElements'总是线性的吗? –