JNI operates Java arrays through jnienv. It provides two functions: one is to operate a simple array of Java, and the other is to operate an array of object types.
For speed reasons, simple arrays are exposed to local code as pointers to local types. Therefore, they can be accessed as regular arrays. This pointer is a pointer to the actual Java array or the copy of the Java array. In addition, the array layout ensures that the local type is matched.
To access arrays of simple Java types, you need to use the getxxxarrayelements function (see table A). xxx represents the array type. This function regards the Java array as a parameter and returns a pointer to the corresponding local array.
Table
Function Java array type
Local type
Getbooleanarrayelements jbooleanarray
Jboolean
Getbytearrayelements jbytearray
Jbyte
Getchararrayelements jchararray
Jchar
Getshortarrayelements jshortarray
Jshort
Getintarrayelements jintarray
Jint
Getlongarrayelements jlongarray
Jlong
Getfloatarrayelements jfloatarray
Jfloat
Getdoublearrayelements jdoublearray
Jdouble
JNI array access function
After you access the array, make sure to call the corresponding releasexxxarrayelements function. The parameter corresponds to the pointer returned by the Java array and getxxxarrayelements. If necessary, this release function will copy any changes you make (so that they are reflected to the Java array) and then release all relevant resources.
To use an array of Java objects, you must use the getobjectarrayelement function and the setobjectarrayelement function to get and set the elements of the array respectively. The getarraylength function returns the length of the array.
The following example shows how to pass an array of the basic type and an array of the object type in Java, and then process it in C ++.
Array transfer:
Code in Java:
Package com. cjz. IBM;
Public class copyarray {
Static int totalsum = 0;
Static int A [] = new int [] {1, 2, 3, 4, 5 };
Static string STR [] = new string [] {"we", "are", "friends "};
Static {
System. loadlibrary ("copyarray ");
}
Private native int sum (INT [] num );
Private native int sum (string [] Str );
Public static void main (string [] ARGs ){
Copyarray CP = new copyarray ();
CP. sum ();
CP. sum (STR );
}
}
In this simple Java program, we define two types of Arrays: an integer array, an array of the basic data type, and an array of the string type, belongs to the object array. Then pass the two types of arrays as parameters to the local method sum. The sum function has the same function name and return value type. The difference between them is the parameter type. In this way, the method signature problem is involved. The method signature is the parameter type + the return value type of the method. We can see that their method signatures are different, so they are two different methods.
After compilation, generate the C ++ header file, this process can refer to the http://blog.csdn.net/chenjin_zhong/archive/2010/09/08/5870305.aspx
C ++ code:
# Include <iostream. h>
# Include <string. h>
# Include "com_cjz_ibm_copyarray.h"
Jniexport jint jnicall java_com_cjz_ibm_copyarray_sum ___ 3I
(Jnienv * ENV, jobject OBJ, jintarray array1 ){
// The input parameter is an integer array.
Jint * arr; // defines an integer pointer.
Int sum = 0;
// The processing of integer arrays mainly includes getintarrayelements and getintarrayregion.
// Method 1
Arr = env-> getintarrayelements (array1, null); // get a pointer to the original data type.
Jint length = env-> getarraylength (array1); // obtain the length of the array.
Int I = 0;
For (I = 0; I <length; I ++ ){
Cout <"arr [" <I <"] =" <arr [I] <Endl;
Sum + = arr [I];
}
// Method 2
Jint Buf [] = {0, 0, 0, 0}; // defines a buffer of the jint type to copy the original array to this Buf.
Env-> getintarrayregion (array1, 0, length, Buf );
For (I = 0; I <length; I ++ ){
Cout <"Buf [" <I <"] =" <Buf [I] <Endl;
Sum + = Buf [I];
}
// Returns an array of the jint type.
// You can input a value to an array and copy the array to jintarray.
Jintarray iarr = env-> newintarray (length); // create a jintarray
Env-> setintarrayregion (iarr, 0, length, Buf); // copy the values in the Buf to the jintarray, and copy the Array
// Print the new array value
Jint * arr2;
Arr2 = env-> getintarrayelements (iarr, null );
For (I = 0; I <env-> getarraylength (iarr); I ++ ){
Cout <"arr2 [" <I <"] =" <arr2 [I] <Endl;
}
Return sum;
}
Jniexport jint jnicall java_com_cjz_ibm_copyarray_sum ___ 3ljava_lang_string_2
(Jnienv * ENV, jobject OBJ, jobjectarray array2 ){
// In Java, the string [] type is an object, so the corresponding array in C ++ is jobjectarray
// Obtain the value in the jobjectarray array.
Int size = env-> getarraylength (array2); // obtain the length of the array.
Int I = 0;
Cout <"output original array value:" <Endl;
For (I = 0; I <size; I ++ ){
Jstring obja = (jstring) ENV-> getobjectarrayelement (array2, I );
Const char * chars = env-> getstringutfchars (obja, null); // convert jstring type to char type output
Cout <chars <Endl;
}
// Copy the array to the new array
Cout <"the copied array is:" <Endl;
Jclass objclass = env-> findclass ("Java/lang/string"); // defines the element type in the array
Jobjectarray texts = env-> newobjectarray (size, objclass, 0); // create an array of the string type.
Jstring jstr;
For (I = 0; I <size; I ++)
{
Jstr = (jstring) ENV-> getobjectarrayelement (array2, I); // obtain the elements in array2
Env-> setobjectarrayelement (texts, I, jstr); // put it in the texts array, which must be placed in jstring
}
For (I = 0; I <size; I ++ ){
Jstring str1 = (jstring) ENV-> getobjectarrayelement (texts, I); // print the newly copied array value
Const char * chars1 = env-> getstringutfchars (str1, null );
Cout <chars1 <Endl;
}
Return 0;
}
In C ++ code, arrays of the int type correspond to jintarray in JNI, while arrays of the string type correspond to jobjectarray.
First, analyze the Code:
Getintarrayelements (<arraytype> array, jboolean * iscopy): the first parameter passes the array name, and the second parameter passes the result of returning a replicated array. Return Value: returns a pointer to an array.
Getintarrayregion (<arraytype> array, jsize start, jsize Len, <nativetype> * BUF)
Array: a reference to an array whose elements are to be copied.
Start: the starting index of the array elements to be copied.
Len: the number of elements to be copied.
Buf: the destination buffer.
Function: Copies elements in jintarray to buffer.
Setintarrayregion (<arraytype> array, jsize start, jsize Len, <nativetype> * BUF)
Array: a reference to a primitive array to which the elements to be copied.
Start: the starting index in the primitive array.
Len: the number of elements to be copied.
Buf: The Source buffer.
Function: copy the elements in Buf to jintarray.
It can be seen that setintarrayregion and getintarrayregion are used to set the jintarray array and retrieve the values in the jintarray array.
Newintarray (jsize length)
Length: the number of elements in the array to be created.
Function: constructs an array object.
Return Value: return a jintarray type.
Getarraylength (<arraytype> array)
Return Value: return the length of jintarray.
In C ++, jintarray cannot be directly accessed by subscript, So it uses the interface functions provided in JNI for operations.
Getobjectarrayelement (jobjectarray array, jsize index)
Array: a reference to the java. Lang. Object array from which the element will be accessed.
Index: the Array Index
Function: returns the object of the corresponding index value. The returned value is the value of an array element.
Setobjectarrayelement (jobjectarray array, jsize index, jobject value)
Array: a reference to an array whose element will be accessed.
Index: Index of the array element to be accessed.
Value: the new value of the array element.
Function: used to set the value of the corresponding index element.
Therefore, we can use get <type> arrayelements and get <type> arrayregion to operate an array of basic types.
Set <type> arrayregion transmits a preset Buf to return a j <type> array. for jobjectarray, you can use setobjectarrayelement and getobjectarrayelement to set the value of the element and the value of the returned element.
This section describes the operations on arrays.
Exception Handling:
The following is a simple example:
Java code:
Ackage com. IBM. cjz;
Public class exception1 {
Private native void doit ();
Private void callback (){
Int A [] = new int [3];
System. Out. println (A [5]); // If the array is out of bounds, an exception occurs in C ++ and the exception is passed to Java in C ++.
}
Public static void main (string [] ARGs ){
Try {
Prediction1 EX = new prediction1 ();
Ex. doit ();
} Catch (exception ex ){
System. Out. println (Ex );
}
}
Static {
System. loadlibrary ("exception ");
}
}
In this Java code, an integer array is defined, and the array is called in the callback () method. We can see that the array is out of bounds, the following shows how to capture this exception in C ++.
C ++ code:
# Include "com_ibm_cjz_exception1.h"
# Include <iostream. h>
# Include <string. h>
Jniexport void jnicall java_com_ibm_cjz_exception1_doit
(Jnienv * ENV, jobject OBJ ){
Jclass CLS = env-> getobjectclass (OBJ );
Jmethodid mid = env-> getmethodid (CLS, "Callback", "() V ");
Env-> callvoidmethod (OBJ, mid );
// Call the callback method to obtain the exception information
Jthrowable excp = 0;
Const char * STR;
Excp = env-> exceptionoccurred (); // get the exception object
If (excp ){
Jclass CLS = env-> getobjectclass (excp );
// Env-> exceptionclear ();
// Env-> predictiondescribe ();
Jmethodid mid = env-> getmethodid (CLS, "tostring", "() ljava/lang/string;"); // call the tostring method in string
Jstring MSG = (jstring) ENV-> callobjectmethod (excp, mid );
STR = env-> getstringutfchars (MSG, null );
Cout <"in C:" <STR <Endl;
Env-> exceptionclear (); // clear this exception so that it cannot be passed to Java
}
Jclass errclass;
Errclass = env-> findclass ("Java/lang/arrayindexoutofboundsexception ");
Env-> thrownew (errclass, "thrown from C ++ Code"); // throws an exception to Java
}
Jthrowable exceptionoccurred (jnienv * env );
Return Value: returns an exception object.
Void exceptionclear (jnienv * env );
Function: clears the exception object and only transmits it in this thread.
Jint thrownew (jnienv * ENV, jclass clazz,
Const char * message );
Function: throws a specified exception object and exception information.
Print result:
In C: Java. Lang. arrayindexoutofboundsexception: 5
Java. Lang. arrayindexoutofboundsexception: thrown from C ++ code
The first line is the information printed in C ++, and the second line is the exception thrown from C ++.
If env-> exceptionclear (); // clear this exception so that it cannot be passed to Java
Jclass errclass;
Errclass = env-> findclass ("Java/lang/arrayindexoutofboundsexception ");
Env-> thrownew (errclass, "thrown from C ++ Code"); // throws an exception to Java
Are commented out, and an exception is thrown to Java. The error is not cleared.