JNI:GetIntArrayElements是否总是线性的?

时间:2017-05-03 14:37:19

标签: java c performance java-native-interface time-complexity

由于我想知道使用JNI来提高应用程序的性能是否值得,我想知道GetIntArrayElements的复杂性是什么。它是否总是在C中分配一个新的原始数组并复制原始Java数组中的所有元素,或者它以某种方式设法传递一个指针?

我想知道将JNI用于线性算法是否值得,例如两个向量的逐点乘法。如果GetIntArrayElements是线性的,我想如果我们需要先复制向量,那么使用C/C++的潜在性能提升会丢失。

1 个答案:

答案 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的缺点是没有数据抽象,就像类'字段有特定类型,字节缓冲区中的位置没有。