Пример #1
0
        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;
        }
Пример #2
0
/**
 * 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;
}