bool release(JNIEnv *env, jint mode=0) { Logger::log(LOG_DEBUGTRACE, "Releasing PointersArrayPointerData %p\n", startPointer); jobjectArray pointersArray = (jobjectArray)env->GetObjectField( nativePointerObject, Pointer_pointers); long size = (long)env->GetArrayLength(pointersArray); void **localPointer = (void**)startPointer; if (mode != JNI_ABORT) { // Write back the values from the native pointers array // into the Java objects for (int i=0; i<size; i++) { jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { return false; } if (p != NULL) { // Check whether the value inside the pointer array has changed. void *oldLocalPointer = arrayPointerDatas[i]->getPointer(env); Logger::log(LOG_DEBUGTRACE, "About to write back pointer %d in PointersArrayPointerData\n", i); Logger::log(LOG_DEBUGTRACE, "Old local pointer was %p\n", oldLocalPointer); Logger::log(LOG_DEBUGTRACE, "New local pointer is %p\n", localPointer[i]); if (localPointer[i] != oldLocalPointer) { Logger::log(LOG_DEBUGTRACE, "In pointer %d setting value %p\n", i, localPointer[i]); bool pointerUpdated = arrayPointerDatas[i]->setNewNativePointerValue(env, (jlong)localPointer[i]); if (!pointerUpdated) { // If the pointer value could not be updated, // (see setNewNativePointerValue documentation) // then there is a pending IllegalArgumentException return false; } } } else if (localPointer[i] != NULL) { // TODO: In future versions, it might be necessary to instantiate // a pointer object here ThrowByName(env, "java/lang/NullPointerException", "Pointer points to an array containing a 'null' entry"); return false; } } } // Release the PointerDatas for the pointer objects that // the pointer points to if (arrayPointerDatas != NULL) { for (int i=0; i<size; i++) { if (arrayPointerDatas[i] != NULL) { if (!releasePointerData(env, arrayPointerDatas[i], mode)) return false; } } delete[] arrayPointerDatas; } delete[] localPointer; env->DeleteGlobalRef(nativePointerObject); return true; }
/** * Release the given PointerData and deletes the PointerData object. * * If the pointerObject of the given pointerData is NULL, the method simply * deletes the pointerData, sets it to NULL and returns true. * * Otherwise, the actions are depending on the memoryType of the pointerData: * * - For NATIVE or DIRECT memory, only the global reference to the * Java pointer object is released * - For ARRAY memory, the respective java primitive array will be released * - For ARRAY_COPY memory, the respective java primitive array will be * released, and the memory will be copied back (except when the given * mode is JNI_ABORT) * - For POINTERS memory, the values of the pointers will be written * back into the nativePointer field of the corresponding Java pointers. * * The method returns whether the respective operation succeeded. */ bool releasePointerData(JNIEnv *env, PointerData* &pointerData, jint mode) { if (pointerData->memoryType == NATIVE || pointerData->memoryType == DIRECT) { Logger::log(LOG_DEBUGTRACE, "Releasing pointer data for direct or native data\n"); env->DeleteGlobalRef(pointerData->pointerObject); delete pointerData; pointerData = NULL; return true; } else if (pointerData->memoryType == ARRAY_COPY) { Logger::log(LOG_DEBUGTRACE, "Releasing host memory from copied array in java buffer\n"); env->ReleasePrimitiveArrayCritical(pointerData->array, (void*)pointerData->startPointer, mode); env->DeleteGlobalRef(pointerData->pointerObject); env->DeleteGlobalRef(pointerData->array); delete pointerData; pointerData = NULL; return true; } else if (pointerData->memoryType == ARRAY) { Logger::log(LOG_DEBUGTRACE, "Releasing host memory from array in java buffer\n"); env->ReleasePrimitiveArrayCritical(pointerData->array, (void*)pointerData->startPointer, JNI_ABORT); env->DeleteGlobalRef(pointerData->pointerObject); env->DeleteGlobalRef(pointerData->array); delete pointerData; pointerData = NULL; return true; } else if (pointerData->memoryType == POINTERS) { Logger::log(LOG_DEBUGTRACE, "Releasing host memory of pointers\n"); // Write the data from the host pointer back into the // Java pointers in the pointer array jobjectArray pointersArray = (jobjectArray)env->GetObjectField( pointerData->pointerObject, NativePointerObject_pointers); jsize size = env->GetArrayLength(pointersArray); void **localPointer = (void**)pointerData->startPointer; for (int i=0; i<size; i++) { // Obtain the native pointer object at the current index, // and set its nativePointer value to the value from the // native array jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { return false; } if (p != NULL) { env->SetLongField(p, NativePointerObject_nativePointer, (jlong)localPointer[i]); env->SetLongField(p, NativePointerObject_byteOffset, 0); } else if (localPointer[i] != NULL) { // If the object at the target position is 'null', but // the value in the native array is not NULL, then try // to create the appropriate pointer object for the // target array and store the non-NULL value in the // created object if (!createPointerObject(env, pointersArray, i, localPointer[i])) { return false; } } } // Release the PointerDatas for the pointer objects that // the pointer points to PointerData **localPointerDatas = pointerData->pointers; if (localPointerDatas != NULL) { for (int i=0; i<size; i++) { if (localPointerDatas[i] != NULL) { if (!releasePointerData(env, localPointerDatas[i])) return false; } } delete[] localPointerDatas; } delete[] (void**)pointerData->startPointer; env->DeleteGlobalRef(pointerData->pointerObject); delete pointerData; pointerData = NULL; return true; } return true; }