📄 ch05.html
字号:
</P><P CLASS="TB"><A NAME="pgfId-1087604"></A><EM CLASS="CODE">GetFloatArrayRegion/SetFloatArrayRegion</EM></P><P CLASS="TB"><A NAME="pgfId-1087605"></A><EM CLASS="CODE">ReleaseFloatArrayRegion </EM></P></TD></TR><TR><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB"><A NAME="pgfId-1087608"></A><EM CLASS="CODE">jint</EM><A NAME="marker-1087607"></A></P></TD><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB"><A NAME="pgfId-1087610"></A><EM CLASS="CODE">NewIntArray </EM></P><P CLASS="TB"><A NAME="pgfId-1087611"></A><EM CLASS="CODE">GetIntArrayElements</EM></P><P CLASS="TB"><A NAME="pgfId-1087612"></A><EM CLASS="CODE">GetIntArrayRegion/SetIntArrayRegion</EM></P><P CLASS="TB"><A NAME="pgfId-1087613"></A><EM CLASS="CODE">ReleaseIntArrayRegion </EM></P></TD></TR><TR><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB"><A NAME="pgfId-1087616"></A><EM CLASS="CODE">jlong</EM><A NAME="marker-1087615"></A></P></TD><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB"><A NAME="pgfId-1087618"></A><EM CLASS="CODE">NewLongArray </EM></P><P CLASS="TB"><A NAME="pgfId-1087619"></A><EM CLASS="CODE">GetLongArrayElements</EM></P><P CLASS="TB"><A NAME="pgfId-1087620"></A><EM CLASS="CODE">GetLongArrayRegion/SetLongArrayRegion</EM></P><P CLASS="TB"><A NAME="pgfId-1087621"></A><EM CLASS="CODE">ReleaseLongArrayRegion </EM></P></TD></TR><TR><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB1"><A NAME="pgfId-1087628"></A><EM CLASS="CODE">jobject</EM><A NAME="marker-1087627"></A></P></TD><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB1"><A NAME="pgfId-1087630"></A><EM CLASS="CODE">NewObjectArray </EM></P><P CLASS="TB"><A NAME="pgfId-1087631"></A><EM CLASS="CODE">GetObjectArrayElement/SetObjectArrayElement</EM></P></TD></TR><TR><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB"><A NAME="pgfId-1087634"></A><EM CLASS="CODE">jshort</EM><A NAME="marker-1087633"></A></P></TD><TD ROWSPAN="1" COLSPAN="1"><P CLASS="TB"><A NAME="pgfId-1087636"></A><EM CLASS="CODE">NewShortArray</EM></P><P CLASS="TB"><A NAME="pgfId-1087637"></A><EM CLASS="CODE">GetShortArrayElements</EM></P><P CLASS="TB"><A NAME="pgfId-1087638"></A><EM CLASS="CODE">GetShortArrayRegion/SetShortArrayRegion </EM></P><P CLASS="TB"><A NAME="pgfId-1087639"></A><EM CLASS="CODE">ReleaseShortArrayRegion</EM></P></TD></TR></TABLE><P CLASS="Body"><A NAME="pgfId-1087640"></A>In the <EM CLASS="CODE">loadFile</EM> native method from the example in the previous section, the entire array is updated by specifying a region that is the size of the file being read in: </P><PRE CLASS="CODE"><A NAME="pgfId-1087641"></A>jbyteArray jb;</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087643"></A>//API Ref: <A NAME="27527"></A>jbyteArray NewByteArray(JNIEnv *env, jsize length)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087646"></A><A NAME="marker-1087644"></A><A NAME="NewByteArray function"></A>jb=(*env)->NewByteArray(env, finfo.st_size);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087648"></A>//API Ref: <A NAME="21508"></A>SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize startelement, jsize length, jbyte *buffer)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087650"></A><A NAME="marker-1087649"></A>(*env)->SetByteArrayRegion(env, jb, 0, finfo.st_size, (jbyte *)m);close(fd);</PRE><P CLASS="Body"><A NAME="pgfId-1087653"></A><A NAME="marker-1087651"></A><A NAME="marker-1087652"></A>The array is returned to the calling Java programming language method, which in turn, garbage collects the reference to the array when it is no longer used. The array can be explicitly freed with the following call. </P><PRE CLASS="CODE-caption"><A NAME="pgfId-1087655"></A>//API Ref: <A NAME="52427"></A>void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087657"></A><A NAME="ReleaseByteArrayElements function"></A>(*env)-> ReleaseByteArrayElements(env, jb, (jbyte *)m, 0);</PRE><P CLASS="Body"><A NAME="pgfId-1087658"></A>The last argument to the <EM CLASS="CODE">ReleaseByteArrayElements</EM> function above can have the following values: </P><UL><LI CLASS="BL"><A NAME="pgfId-1087659"></A><EM CLASS="CODE">0:</EM> Updates to the array from within the C code are reflected in the Java programming language copy.</LI><LI CLASS="BL"><A NAME="pgfId-1087661"></A><EM CLASS="CODE">JNI_COMMIT</EM><A NAME="marker-1087660"></A>: The Java programming language copy is updated, but the local <EM CLASS="CODE">jbyteArray</EM> is not freed. </LI><LI CLASS="BL"><A NAME="pgfId-1087663"></A><A NAME="marker-1087662"></A>JNI_ABORT: Changes are not copied back, but the <EM CLASS="CODE">jbyteArray</EM> is freed. The value is used only if the array is obtained with a get mode of <EM CLASS="CODE">JNI_TRUE,</EM> meaning the array is a copy.</LI></UL><P CLASS="Body"><A NAME="pgfId-1087664"></A>See Memory Issues (page 155) for more information on memory management.</P></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087665"></A>Pinning Arrays</H5><P CLASS="Body"><A NAME="pgfId-1087668"></A><A NAME="marker-1087666"></A><A NAME="marker-1087667"></A>When retrieving an array, you can specify if this is a copy (<EM CLASS="CODE">JNI_TRUE</EM>) or a reference to the array residing in your Java program (<EM CLASS="CODE">JNI_FALSE</EM>). If you use a reference to the array, you will want the array to stay where it is in the Java heap and not get moved by the garbage collector when it compacts heap memory. To prevent the array references from being moved, the Java virtual machine pins the array into memory. Pinning the array ensures that when the array is released, the correct elements are updated in the Java virtual machine. </P><P CLASS="Body"><A NAME="pgfId-1087671"></A><A NAME="marker-1087669"></A><A NAME="marker-1087670"></A>In the loadfile native method example from the previous section, the array is not explicitly released. One way to ensure the array is garbage collected when it is no longer needed is to call a Java method, pass the byte array instead, and free the local array copy. This technique is shown in the section on Multidimensional Arrays (page 145). </P></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087672"></A>Object Arrays</H5><P CLASS="Body"><A NAME="pgfId-1087677"></A><A NAME="marker-1087673"></A><A NAME="marker-1087674"></A>You can store any Java object in an array with the <EM CLASS="CODE">NewObjectArray</EM><A NAME="marker-1087675"></A> and <EM CLASS="CODE">SetObjectArrayElement</EM><A NAME="marker-1087676"></A> function calls. The main difference between an object array and an array of primitive types is that when constructing a <EM CLASS="CODE">jobjectArray</EM><A NAME="marker-1087678"></A>, the Java class is used as a parameter. </P><P CLASS="Body"><A NAME="pgfId-1087679"></A>This next C++ example shows how to call <EM CLASS="CODE">NewObjectArray</EM> to create an array of <EM CLASS="CODE">String</EM> objects. The size of the array is set to five, the class definition is returned from a call to <EM CLASS="CODE">FindClass</EM><A NAME="marker-1087680"></A>, and the elements of the array are initialized with an empty string. The elements of the array are updated by calling <EM CLASS="CODE">SetObjectArrayElement</EM><A NAME="marker-1087681"></A> with the position and value to put in the array. </P><PRE CLASS="CODE"><A NAME="pgfId-1087682"></A>/* ReturnArray.C */ </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087683"></A>#include <jni.h>#include "ArrayHandler.h" JNIEXPORT jobjectArray JNICALL Java_ArrayHandler_returnArray</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087684"></A> (JNIEnv *env, jobject jobj){ jobjectArray ret; int i; char *message[5]= {"first", "second", "third", "fourth", "fifth"}; ret = (jobjectArray)env->NewObjectArray(5,</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087686"></A>//API Ref: <A NAME="76065"></A>jclass FindClass(JNIenv *env, const char *name)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087689"></A> <A NAME="marker-1087687"></A><A NAME="FindClass function"></A>env->FindClass("java/lang/String"),</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087691"></A>//API Ref: <A NAME="84476"></A>jstring NewStringUTF(JNIEnv *env, const char *bytes)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087693"></A> <A NAME="marker-1087692"></A>env->NewStringUTF("")); for(i=0;i<5;i++) {</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087695"></A>//API Ref: <A NAME="46911"></A>void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087698"></A> <A NAME="marker-1087696"></A><A NAME="SetObjectArrayElement function"></A>env->SetObjectArrayElement(ret,i,env->NewStringUTF(message[i])); } return(ret); }</PRE><P CLASS="Body"><A NAME="pgfId-1087699"></A>The Java class that calls this native method is as follows: </P><PRE CLASS="CODE"><A NAME="pgfId-1087700"></A>//ArrayHandler.java </PRE><PRE CLASS="CODE"><A NAME="pgfId-1087701"></A>public class ArrayHandler { public native String[] returnArray(); static{</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087703"></A>//API Ref: <A NAME="21064"></A>static void loadLibrary(String libraryname)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087705"></A> <A NAME="marker-1087704"></A>System.loadLibrary("nativelib"); } public static void main(String args[]) { String ar[]; ArrayHandler ah= new ArrayHandler(); ar = ah.returnArray(); for(int i=0; i<5; i++) { System.out.println("array element"+i+ "=" + ar[i]); } } }</PRE></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087708"></A><A NAME="27586"></A>Multi<A NAME="marker-1087707"></A>dimensional Arrays</H5><P CLASS="Body"><A NAME="pgfId-1087712"></A><A NAME="marker-1087709"></A>You might need to call existing numerical and mathematical libraries such as the <A NAME="marker-1087710"></A><A NAME="marker-1087711"></A>linear algebra library <EM CLASS="CODE">CLAPACK/LAPACK</EM><A NAME="marker-1087713"></A> or other matrix-crunching programs from your Java program using native methods. Many of these libraries and programs use two-dimensional and higher-order arrays. </P><P CLASS="Body"><A NAME="pgfId-1087714"></A>In the Java programming language, any array that has more than one dimension is treated as an array of arrays. For example, a two-dimensional integer array is handled as an array of integer arrays. The array is read horizontally, or in what is also termed as row order. </P><P CLASS="Body"><A NAME="pgfId-1087716"></A>Other languages such as <A NAME="marker-1087715"></A>FORTRAN use column ordering, so extra care is needed if your program hands a Java array to a FORTRAN function. Also, the array elements in an application written in the Java programming language are not guaranteed to be contiguous in memory. Some numerical libraries use the knowledge that the array elements are stored next to each other in memory to perform speed optimizations, so you might need to make an additional local copy of the array to pass to those functions. </P><P CLASS="Body"><A NAME="pgfId-1087717"></A>The next example passes a two-dimensional array to a native method, which then extracts the elements, performs a calculation, and calls a Java method to return the results. The array is passed as an object array that contains an array of <EM CLASS="CODE">jint</EM>s. The individual elements are extracted by first retrieving a <EM CLASS="CODE">jintArray</EM> instance from the object array by calling <EM CLASS="CODE">GetObjectArrayElement</EM><A NAME="marker-1087718"></A>, and then extracting the elements from the <EM CLASS="CODE">jintArray</EM> row. </P><P CLASS="Body"><A NAME="pgfId-1087719"></A>The example uses a fixed-size matrix. If you do not know the size of the array being used, the <EM CLASS="CODE">GetArrayLength(array)</EM><A NAME="marker-1087720"></A> function returns the size of the outermost array. You will need to call the <EM CLASS="CODE">GetArrayLength(array)</EM> function on each dimension of the array to discover the total size of the array. The new array sent back to the program written in the Java language is built in reverse. First, a <EM CLASS="CODE">jintArray</EM><A NAME="marker-1087721"></A> instance is created and that instance is set in the object array by calling <EM CLASS="CODE">SetObjectArrayElement</EM>. </P><PRE CLASS="CODE"><A NAME="pgfId-1087722"></A>public class ArrayManipulation { private int arrayResults[][]; Boolean lock=new Boolean(true); int arraySize=-1; public native void manipulateArray(int[][] multiplier, Boolean lock); static{</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087724"></A>//API Ref: <A NAME="22659"></A>static void loadLibrary(String libraryname)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087726"></A> <A NAME="marker-1087725"></A>System.loadLibrary("nativelib"); } public void sendArrayResults(int results[][]) { arraySize=results.length; arrayResults=new int[results.length][]; System.arraycopy(results,0,arrayResults, 0, arraySize); } public void displayArray() { for (int i=0; i<arraySize; i++) { for(int j=0; j <arrayResults[i].length;j++) { System.out.println("array element "+i+","+j+ "= " + arrayResults[i][j]); } } } public static void main(String args[]) { int[][] ar = new int[3][3]; int count=3; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { ar[i][j]=count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -