The Java TM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: Java Native Interface
Lesson: Interacting with Java from the Native Side

## Accessing Java Arrays

> The JNI uses the `jarray` type to represent references to Java arrays. Similar to `jstring`, you cannot directly access `jarray` types in your native method C code. Instead, you use functions provided by the JNI that allow you to obtain pointers to elements of integer arrays.

> Our second example, `IntArray.java`, contains a native method that totals up the contents of an integer array passed to it from a Java application. You cannot implement the native method by directly addressing the array elements. The following code snippet incorrectly tries to access the array elements directly:

>     /*  This program is illegal! */
>     JNIEXPORT jint JNICALL
>     Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
>     {
>         int i, sum = 0;
>         for (i=0; i<10; i++) {
>             sum += arr[i];
>         }
>         ...

> The C program `IntArray.c` shows the correct way to implement the above function `Java_IntArray_sumArray`. In this example, you use one JNI function to get the length of the array. Use another JNI function to obtain a pointer to the individual elements of the array. Then, you can retrieve the elements. Lastly, use a third JNI function to release the array memory.

### Accessing Arrays of Primitive Elements

First, obtain the length of the array by calling the JNI function `GetArrayLength`.

> Note: Unlike C language arrays, Java arrays carry length information.

>     JNIEXPORT jint JNICALL
>     Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
>     {
>         int i, sum = 0;
>         jsize len = (*env)->GetArrayLength(env, arr);
>         ...

Next, obtain a pointer to the elements of the array. Our example contains an integer array so we use the JNI function `GetIntArrayElements` to obtain this pointer. Once you obtain the pointer, you can use normal C language operations on the resulting integer array.

>     {
>         ...
>         jint *body = (*env)->GetIntArrayElements(env, arr, 0);
>         for (i=0; i<len; i++) {
>             sum += body[i];
>         }
>         ...

The JNI provides a set of functions to obtain array element pointers; use the function that corresponds to the primitive type of the array. Had our example contained a float array `arr`, for example, we would have used the JNI function `GetFloatArrayElements` to obtain a pointer to its elements, as follows:

>         ...
>         int i;
>         float sum = 0;
>         ...
>         jfloat *body = (*env)->GetFloatArrayElements(env, arr, 0);
>         for (i=0; i<len; i++) {
>             sum += body[i];
>         }
>         ...

In general, the garbage collector may move Java arrays. However, the Java Virtual Machine guarantees that the result of `GetIntArrayElements` points to a nonmovable array of integers. The JNI will either "pin" down the array or it will make a copy of the array into nonmovable memory. Because of this, the native code must call `ReleaseIntArrayElements` when it has finished using the array, as follows:

>         ...
>         (*env)->ReleaseIntArrayElements(env, arr, body, 0);
>         return sum;
>     }

ReleaseIntArrayElements enables the JNI to copy back and free the memory referenced by the `body` parameter if it is a copy of the original Java array. The "copy back" action enables the calling program to obtain the new values of array elements that the native method may have modified. `ReleaseIntArrayElements` will "unpin" the Java array if it has been pinned in memory.

Similar to the `Get<type>ArrayElements` functions, the JNI provides a set of `Release<type>ArrayElements` functions. Do not forget to call the appropriate `Release<type>ArrayElements` function, such as `ReleaseIntArrayElements`. If you forget to make this call, the array stays pinned for an extended period of time. Or, the Java Virtual Machine is unable to reclaim the memory used to store the nonmovable copy of the array.

The JNI provides a set of functions to access arrays of every primitive type, including `boolean`, `byte`, `char`, `short`, `int`, `long`, `float`, and `double`. Each function in the following table accesses elements in the specified Java type of array:

> ##### JNI Functions for Accessing Arrays

> Function | Array Type
> | `GetBooleanArrayElements` | `boolean` | `GetByteArrayElements` | `byte` | `GetCharArrayElements` | `char` | `GetShortArrayElements` | `short` | `GetIntArrayElements` | `int` | `GetLongArrayElements` | `long` | `GetFloatArrayElements` | `float` | `GetDoubleArrayElements` | `double`

The JNI also provides a set of functions to release arrays of different primitive types. The following table summarizes these functions.

> ##### JNI Functions for Releasing Arrays

> Function | Array Type
> | `ReleaseBooleanArrayElements` | `boolean` | `ReleaseByteArrayElements` | `byte` | `ReleaseCharArrayElements` | `char` | `ReleaseShortArrayElements` | `short` | `ReleaseIntArrayElements` | `int` | `ReleaseLongArrayElements` | `long` | `ReleaseFloatArrayElements` | `float` | `ReleaseDoubleArrayElements` | `double`

### Accessing a Small Number of Elements

Note that the `Get<type>ArrayElements` function might potentially copy the entire array. You may want to limit the number of elements that are copied, especially if your array is large. If you are only interested in a small number of elements in a (potentially) large array, you should instead use the `Get/Set<type>ArrayRegion` functions. These functions allow you to access, via copying, a small set of elements in an array.

### Accessing Arrays of Objects

The JNI provides a separate set of functions to access elements of object arrays. You can use these functions to get and set individual object array elements.

> Note: You cannot get all the object array elements at once.

- `GetObjectArrayElement` returns the object element at a given index.
- `SetObjectArrayElement` updates the object element at a given index.

| Start of Tutorial > Start of Trail > Start of Lesson | Search