由于我想知道使用JNI
来提高应用程序的性能是否值得,我想知道GetIntArrayElements
的复杂性是什么。它是否总是在C
中分配一个新的原始数组并复制原始Java
数组中的所有元素,或者它以某种方式设法传递一个指针?
我想知道将JNI
用于线性算法是否值得,例如两个向量的逐点乘法。如果GetIntArrayElements
是线性的,我想如果我们需要先复制向量,那么使用C/C++
的潜在性能提升会丢失。
答案 0 :(得分:1)
GetIntArrayElements
有一个名为isCopy
的可选引用参数。当VM为您提供数据副本时,此参数将设置为JNI_TRUE
。我们的想法是,不同的VM实现可能具有不同的数组内存表示形式,也与C期望的内存布局不兼容。
通常,在Java和本机代码之间共享内存的最快方法是使用直接ByteBuffer
s(使用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
的缺点是没有数据抽象,就像类'字段有特定类型,字节缓冲区中的位置没有。