JNI 缓存 Java 数组

JNI cache java array

本文关键字:数组 Java 缓存 JNI      更新时间:2023-10-16

我有一个java应用程序和一些原生的c ++代码。Java 应用程序运行一些线程。每个线程都有一个双精度数组,该数组作为参数传递给本机代码。到目前为止,一切正常。现在在我的本机代码中,我想在数组中写入值。目前,我通过以下方式执行此操作:

  JNIEXPORT void JNICALL Java_JNIPerformanceTest_alterArray___3I_3D
    (JNIEnv *env, jobject, jintArray intArray, jdoubleArray doubleArray){
         jint count = env->GetArrayLength(doubleArray);
         jdouble* S_native = env->GetDoubleArrayElements(doubleArray, NULL);
         for (int i=0; i < count; i++) {
                S_native[i] = i;
         }
         jint count2 = env->GetArrayLength(intArray);
         jint* S_native2 = env->GetIntArrayElements(intArray, NULL);

         for (int i=0; i < count2; i++) {
                S_native2[i] = i;
         }
         env->ReleaseDoubleArrayElements(doubleArray, S_native, 0);
         env->ReleaseIntArrayElements(intArray, S_native2, 0);
    }

由于 GetArrayLength 和 GetDoubleArrayElements 需要一些时间,并且我总是将相同的 java 数组实例传递给本机代码,我想知道是否有解决方案无需获取元素指针并释放函数调用。我已经尝试在全球范围内存储指针,当然

 env->NewWeakGlobalRef(array);

.但是如果我不在这个数组上调用 ReleaseDoubleArrayElements,那么如果在 java 中检查元素,元素不会改变。解决此类问题的最佳方法是什么?使用 ByteBuffer?

这也是我的java代码:

    double ARRAY_SIZE = 10;
    for (int i = 0; i < 4; i++) {
        Thread thread = new Thread(new Runnable() {
            boolean done = false;
            @Override
            public void run() {
                while (true) {
                    double d[] = null;
                    int intArray[] = null;
                    if (!done) {
                        d = new double[ARRAY_SIZE];
                        for (int i = 0; i < ARRAY_SIZE; i++) {
                            d[i] = 222;
                        }
                        intArray = new int[ARRAY_SIZE];
                    }
                    long start = System.nanoTime();
                    alterArray(intArray, d);
                    long end = System.nanoTime();
                    System.out.println("test_alterArray: time for " + NUM_LOOPS + " loops: " + ((end - start) / 1000) + " us.");
                }
            }
        });
        thread.start();
    }

是的,正确的方法是使用 DirectByteBuffer .不过,它有其自身的缺点。例如,这样的 Buffer 不受数组支持,从 Java 端访问它可能效率较低。