Accessing Array Elements in Java

All array types of the Java programming language have corresponding C types, as shown in Table 12.2.

The GetArrayLength function returns the length of an array.

jarray array = . . .;

jsize length = (*env)->GetArrayLength(env, array);

How you access elements in an array depends on whether the array stores objects or values of a primitive type (bool, char, or a numeric type). To access elements in an object array, use the GetObjectArrayElement and SetObjectArrayElement methods.

 

Figure 12.3 Inheritance hierarchy of array types

jobjectArray array = . . int i, j;

jobject x = (*env)->GetObjectArrayElement(env, array, i);

(*env)->SetObjectArrayElement(env, array, j, x);

Although simple, this approach is also clearly inefficient; you want to be able to access array elements directly, especially when doing vector and matrix computations.

The GetXxxArrayElements function returns a C pointer to the starting element of an array. As with ordinary strings, you must remember to call the correspond­ing ReleaseXxxArrayElements function to tell the virtual machine when you no longer need that pointer. Here, the type Xxx must be a primitive type—that is, not Object. You can then read and write the array elements directly. How­ever, since the pointer might point to a copy, any changes that you make are guaranteed to be reflected in the original array only after you call the corresponding ReteaseXxxArrayEtements function!

Here is an example that multiplies all elements in an array of double values by a constant. We obtain a C pointer a into the Java array and then access individual elements as a[i].

jdoubleArray array_a = . . .;

double scaleFactor = . . .;

double* a = (*env)->GetDoubleArrayElements(env, array_a, NULL);

for (i = 0; i < (*env)->GetArrayLength(env, array_a); i++)

a[i] = a[i] * scaleFactor;

(*env)->ReleaseDoubleArrayElements(env, array_a, a, 0);

Whether the virtual machine actually copies the array depends on how it allocates arrays and does its garbage collection. Some “copying” garbage col­lectors routinely move objects around and update object references. That strategy is not compatible with “pinning” an array to a particular location, because the collector cannot update the pointer values in native code.

To access just a few elements of a large array, use the GetXxxArrayRegion and SetXxxArrayRegion methods that copy a range of elements from the Java array into a C array and back.

You can create new Java arrays in native methods with the NewXxxArray function. To create a new array of objects, specify the length, the type of the array ele­ments, and an initial element for all entries (typically, NULL). Here is an example:

jclass ctass_Emptoyee = (*env)->FindCtass(env, “Employee”);

jobjectArray array_e = (*env)->NewObjectArray(env, 100, class_Employee, NULL);

Arrays of primitive types are simpler: Just supply the length of the array.

jdoubleArray array_d = (*env)->NewDoubleArray(env, 100);

The array is then filled with zeroes.

Source: Horstmann Cay S. (2019), Core Java. Volume II – Advanced Features, Pearson; 11th edition.

Leave a Reply

Your email address will not be published. Required fields are marked *