Skip to content
Eugene Gershnik edited this page Oct 9, 2021 · 5 revisions

SimpleJNI provides support for C++ friendly uniform access to Java arrays: both of primitive types and Java objects. Recall from Declaring Java Types that you need to declare Java object array types via

DEFINE_ARRAY_JAVA_TYPE(jSomething);

This is required in order for the following to work.

You can create a new Java array as follows

JNIEnv * env = ...;
//Primitive type. Create int[25]
local_java_ref<jintArray> intArray = java_array_create<jint>(env, 25);

//Object type. Create Something[25] initialized to null
const auto & classOfSomething = java_classes::get<ClassOfSomething>();
local_java_ref<jSomethingArray> somethingArray = java_array_create(env, classOfSomething, 25, nullptr);

You access elements of Java arrays using java_array_access class that present STL-compatible interface. For primitive types

java_array_access elements(env, intArray.c_ptr());

jsize size = elements.size();
jint x = elements[3];
elements[3] = 7;

for(jint val: elements)
{
    std::cout << val << ' '; 
}

for(jint & val: elements)
{
    val = 42;
}
//Must call commit() to save changes and make them visible to Java. 
//Second argument being false indicates that we are not done yet and can still make more changes.
elements.commit(env, false);

for(jint & val: elements)
{
    val = 24;
}
//Must call commit() to save changes and destroy access object. Don't use it after that
elements.commit(env); 

The commit() method must be called if you made any changes to the array's element. If you don't call it all your changes will be discarded when access object is destroyed. See documentation for JNI's ReleaseArrayElements and it's various flags for more details. The second argument: done maps to JNI's flags as follows

  • true (default): 0. Copy back the content and destroy the access object
  • false: JNI_COMMIT. Copy back the content but do not destroy the access object If commit() is not called the destruct will release the elements with JNI_ABORT flag.

For object type you also use java_array_access<T> object but elements are accessed one by one and there is no commit() method.

java_array_access elements(env, somethingArray.c_ptr());

jsize size = elements.size();
local_java_ref<jSomething> x = elements[3];
elements[3] = ...;

//don't use auto here! elements sequence returns proxies
for(local_java_ref<jSomething> obj: elements)
{
    //use obj
}

for(auto & obj: elements)
{
    obj = ...;
}