2010年9月27日 星期一

JNI - Arguments Passing: Object Arrays

  • Accessing Object Arrays
    1. (example) ObjectArrayTest.java: calls a native method to create a two-dimensional array of int and then prints the content of the array.
    2. class ObjectArrayTest {
          private static native int[][] initInt2DArray(int size);
          public static void main(String[] args) {
              int len = 5;
              int[][] i2arr = initInt2DArray(len);
              for (int i = 0; i < len; i++) {
                  for (int j = 0; j < len; j++) {
                      System.out.print(" " + i2arr[i][j]);
                  }
                  System.out.println();
              }
          }
          static {
              System.loadLibrary("ObjectArrayTest");
          }
      }
      
    3. Generate C/C++ header file
    4. ObjectArrayTest.h
      /* DO NOT EDIT THIS FILE - it is machine generated */                           
      #include <jni.h>
      /* Header for class ObjectArrayTest */
      
      #ifndef _Included_ObjectArrayTest
      #define _Included_ObjectArrayTest
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class:     ObjectArrayTest
       * Method:    initInt2DArray
       * Signature: (I)[[I
       */
      JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray
        (JNIEnv *, jclass, jint);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      
    5. Implementation of ObjectArrayTest.c
    6. ObjectArrayTest.c
      • The static native method initInt2DArray creates a two-dimensional array of the given size.
      JNIEXPORT jobjectArray JNICALL
       Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclass cls, int size)
       {
           jobjectArray result;
           int i;
           jclass intArrCls = (*env)->FindClass(env, "[I");
           if (intArrCls == NULL) {
               return NULL; /* exception thrown */
           }
           result = (*env)->NewObjectArray(env, size, intArrCls,
                                           NULL);
           if (result == NULL) {
               return NULL; /* out of memory error thrown */
           }
           for (i = 0; i < size; i++) {
               jint tmp[256];  /* make sure it is large enough! */
               int j;
               jintArray iarr = (*env)->NewIntArray(env, size);
               if (iarr == NULL) {
                   return NULL; /* out of memory error thrown */
               }
               for (j = 0; j < size; j++) {
                   tmp[j] = i + j;
               }
               (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);
               (*env)->SetObjectArrayElement(env, result, i, iarr);
               (*env)->DeleteLocalRef(env, iarr);
           }
           return result;
       }
      
      • FindClass(): to obtain a reference of the element class of the two-dimensional int array.
      • FindClass() returns NULL and throws an exception if class loading fails. (for example, a missing class file or an out-of-memory condition)
      • The "[I" argument to FindClass is the JNI class descriptor that corresponds to the int[ ] type in the Java programming language.
      • NewObjectArray(): allocates an array whose element type is denoted by the intArrCls class reference.
      • NewIntArray(): allocates the individual array elements.
      • SetIntArrayRegion(): copies the contents of the tmp[ ] buffer into the newly allocated one-dimensional arrays.
      • SetObjectArrayElement(): sets the jth element of the ith one-dimensional array has value i+j.
      • DeleteLocalRef(): ensures that the virtual machine does not run out of the memory used to hold JNI references such as iarr.
    7. Generate shared library file - libObjectArrayTest.so
    8. cc -shared -I/usr/local/jdk1.6.20_21/include -I/usr/local/jdk1.6.20_21/include/linux ObjectArrayTest.c -o libObjectArrayTest.so
    9. Run ObjectArrayTest output (size=5):
    10. 0 1 2 3 4
      1 2 3 4 5
      2 3 4 5 6
      3 4 5 6 7
      4 5 6 7 8

0 意見: