bool init(JNIEnv *env, jobject object) { // Create a global reference to the given object nativePointerObject = env->NewGlobalRef(object); if (nativePointerObject == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while creating global reference for pointer data"); return false; } jobjectArray pointersArray = (jobjectArray)env->GetObjectField( object, Pointer_pointers); long size = (long)env->GetArrayLength(pointersArray); // Prepare the pointer that points to the pointer // values of the NativePointerObjects void **localPointer = new void*[size]; if (localPointer == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while initializing pointer array"); return false; } startPointer = (void*)localPointer; // Prepare the PointerData objects for the Java NativePointerObjects arrayPointerDatas = new PointerData*[size]; if (arrayPointerDatas == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while initializing pointer data array"); return false; } // Initialize the PointerDatas and the pointer values // from the NativePointerObjects in the Java Pointer. for (int i=0; i<size; i++) { jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { return false; } if (p != NULL) { // Initialize a PointerData for the pointer object that // the pointer points to PointerData *arrayPointerData = initPointerData(env, p); if (arrayPointerData == NULL) { return false; } arrayPointerDatas[i] = arrayPointerData; localPointer[i] = arrayPointerData->getPointer(env); } else { arrayPointerDatas[i] = NULL; localPointer[i] = NULL; } } // Obtain the byteOffset byteOffset = env->GetLongField(object, Pointer_byteOffset); if (env->ExceptionCheck()) { return false; } Logger::log(LOG_DEBUGTRACE, "Initialized PointersArrayPointerData %p\n", startPointer); return true; }
/** * Initializes a PointerData with the data from the given Java NativePointerObject. * * If the given pointerObject is NULL, the method simply sets the startPointer * and pointer of the pointerData to NULL and returns it. * * Otherwise, this method will initialize the startPointer of the PointerData, * and the pointer of the PointerData will be set to * startPointer+byteOffset * where byteOffset is the byteOffset that is obtained from the Java Pointer * object. * * By default, the startPointer of the PointerData will be initialized with * the native pointer value from the given Java Pointer object. If this * startPointer is non-NULL, the method sets memoryType to NATIVE and * returns it. * * If the array of Java Pointers that the Pointer points to is non-NULL, then * the startPointer of the PointerData be set to point to an array of * void* pointers that correspond to the values of the Java Pointers * from the array. If this array can be created, the method sets the * memoryType to POINTERS and returns the PointerData. * * If the Buffer of the Pointer is non-null, then the startPointer will be * obtained from the buffer: * - If the Buffer is direct, this method sets the startPointer to the * direct buffer address, sets memoryType to DIRECT and returns the * PointerData * - If the buffer has an array, the method sets the startPointer to the * array, sets memoryType to ARRAY or ARRAY_COPY, indicating whether * the array was pinned or copied, and returns the PointerData. * * If none of these attempts of obtaining the startPointer was * successful, then the method returns the empty PointerData. * * If an Exception occurs, NULL is returned. */ PointerData* initPointerData(JNIEnv *env, jobject pointerObject) { Logger::log(LOG_DEBUGTRACE, "Initializing pointer data for Java Pointer object %p\n", pointerObject); PointerData *pointerData = new PointerData(); if (pointerData == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while initializing pointer data"); return NULL; } pointerData->startPointer = (jlong)NULL; pointerData->pointer = (jlong)NULL; pointerData->memoryType = NATIVE; if (pointerObject == NULL) { return pointerData; } else { pointerData->pointerObject = env->NewGlobalRef(pointerObject); if (pointerData->pointerObject == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while creating reference to pointer object"); return NULL; } } pointerData->startPointer = env->GetLongField(pointerData->pointerObject, NativePointerObject_nativePointer); // Set the actual pointer to be the startPointer + the byte offset long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); if (pointerData->startPointer != (jlong)NULL) { Logger::log(LOG_DEBUGTRACE, "Obtaining native pointer %p\n", (void*)pointerData->startPointer); pointerData->memoryType = NATIVE; return pointerData; } // Obtain the array of pointers the pointer points to jobjectArray pointersArray = (jobjectArray)env->GetObjectField(pointerObject, NativePointerObject_pointers); if (pointersArray != NULL) { Logger::log(LOG_DEBUGTRACE, "Obtaining pointers in host memory\n"); // Create an array containing the native representations of the // pointers, and store them as the data of the pointerData jsize size = env->GetArrayLength(pointersArray); void **localPointer = new void*[(size_t)size]; PointerData **localPointerDatas = new PointerData*[(size_t)size]; if (localPointer == NULL) { ThrowByName(env, "java/lang/OutOfMemoryError", "Out of memory while obtaining native pointers"); return NULL; } for (int i=0; i<size; i++) { jobject p = env->GetObjectArrayElement(pointersArray, i); if (env->ExceptionCheck()) { return NULL; } if (p != NULL) { // Initialize a PointerData for the pointer object that // the pointer points to PointerData *localPointerData = initPointerData(env, p); if (localPointerData == NULL) { return NULL; } localPointerDatas[i] = localPointerData; localPointer[i] = (void*)localPointerData->startPointer; } else { localPointerDatas[i] = NULL; localPointer[i] = NULL; } } pointerData->pointers = localPointerDatas; pointerData->startPointer = (jlong)localPointer; // Set the actual pointer to be the startPointer + the byte offset long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); pointerData->memoryType = POINTERS; return pointerData; } jobject buffer = env->GetObjectField(pointerObject, NativePointerObject_buffer); if (buffer != NULL) { // Check if the buffer is direct jboolean isDirect = env->CallBooleanMethod(buffer, Buffer_isDirect); if (env->ExceptionCheck()) { return NULL; } if (isDirect==JNI_TRUE) { Logger::log(LOG_DEBUGTRACE, "Obtaining host memory from direct java buffer\n"); // Obtain the direct buffer address from the given buffer pointerData->startPointer = (jlong)env->GetDirectBufferAddress(buffer); if (pointerData->startPointer == 0) { ThrowByName(env, "java/lang/IllegalArgumentException", "Failed to obtain direct buffer address"); return NULL; } pointerData->memoryType = DIRECT; // Set the actual pointer to be the startPointer + the byte offset long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); return pointerData; } // Check if the buffer has an array jboolean hasArray = env->CallBooleanMethod(buffer, Buffer_hasArray); if (env->ExceptionCheck()) { return NULL; } if (hasArray==JNI_TRUE) { Logger::log(LOG_DEBUGTRACE, "Obtaining host memory from array in java buffer\n"); long byteOffset = (long)env->GetLongField(pointerObject, NativePointerObject_byteOffset); jarray localArray = (jarray)env->CallObjectMethod(buffer, Buffer_array); if (env->ExceptionCheck()) { return NULL; } jarray globalArray = (jarray)env->NewGlobalRef(localArray); if (globalArray == NULL) { return NULL; } pointerData->array = globalArray; jboolean isCopy = JNI_FALSE; pointerData->startPointer = (jlong)env->GetPrimitiveArrayCritical(globalArray, &isCopy); if (pointerData->startPointer == 0) { return NULL; } if (isCopy==JNI_TRUE) { pointerData->memoryType = ARRAY_COPY; } else { pointerData->memoryType = ARRAY; } // Set the actual pointer to be the startPointer + the byte offset pointerData->pointer = (jlong)(((char*)pointerData->startPointer)+byteOffset); return pointerData; } // The buffer is neither direct nor has an array - should have // been checked on Java side Logger::log(LOG_ERROR, "Buffer is neither direct nor has an array\n"); ThrowByName(env, "java/lang/IllegalArgumentException", "Buffer is neither direct nor has an array"); return NULL; } return pointerData; }