JNI 를 통해 배열을 다루는 방법 중, 지난 강좌에 못 다룬 부분들에 대한 내용을 추가해 보겠습니다

 

JNI 에서는 c/c++ 레벨에서 java 배열을 생성하고, 값을  set 하는 함수를 제공하고 있습니다.

 

===== (5) 배열 다루기 2 =================================================================

 

1. 예제

 

MainStart.java

public class MainStart {
        public static void main(String[] args) {
                int[] iArray;

 

                iArray = JniFunctions.makeIntArray(10);
                JniFunctions.setIntArray(iArray, 123);

 

                System.out.println("Array len = " + iArray.length);
                for(int i=0; i<iArray.length; i++) {
                        System.out.println("Array [" + i + "] = " + iArray[i]);
                }
        }
}

JniFunctions.java

public class JniFunctions {
        static {
                System.loadLibrary("mylib");
        }

        public static native int[] makeIntArray(int len);
        public static native int setIntArray(int[] arr, int value);

}

c/c++ 레벨에서 배열을 생성해서 반환하는 함수 : makeIntArray()

c/c++ 레벨에서 배열에 값을 설정하는 함수 : setIntArray()

 

JniFunctions.cpp

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>

 

#ifdef __cplusplus
extern "C" {
#endif


JNIEXPORT jintArray JNICALL Java_JniFunctions_makeIntArray
  (JNIEnv *env, jclass cls, jint arr_len)
{
        jintArray ji_array = NULL;

        ji_array = env->NewIntArray(arr_len);


        if(ji_array != NULL) {
                printf("In JNI >> new int array : %d\n", arr_len);
                return ji_array;
        }
        else {
                printf("In JNI >> fail make new int array\n");
                return NULL;
        }
}

 

JNIEXPORT jint JNICALL Java_JniFunctions_setIntArray
  (JNIEnv *env, jclass cls, jintArray ji_array, jint value)
{
        int len, i;
        jint *int_buf;

 

        len = env->GetArrayLength(ji_array);
        int_buf = (jint *)malloc(sizeof(jint) * len);
        if(int_buf == NULL) {
                printf("In JNI >> fail allocate memory\n");
                return 0;
        }

 

        for(i=0; i<len; i++)
                int_buf[i] = value;
        env->SetIntArrayRegion(ji_array, 0, len, (const jint *)int_buf);

 

        free(int_buf);

        return len;
}

 

#ifdef __cplusplus
}
#endif

 

실행 및 결과

$ javac JniFunctions.java
$ javac MainStart.java
$ g++ -shared -o libmylib.so JniFunctions.cpp -I/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java-6-openjdk/include/linux/

$ export LD_LIBRARY_PATH=./
$ java MainStart
In JNI >> new int array : 10
Array len = 10
Array [0] = 123
Array [1] = 123
Array [2] = 123
Array [3] = 123
Array [4] = 123
Array [5] = 123
Array [6] = 123
Array [7] = 123
Array [8] = 123
Array [9] = 123

 

2. 메모리 관리.

NewIntArray() 와 SetIntArrayRegion() 을 사용하면서 메모리 관리에 대한 의문이 들 수 밖에 없다.

java 의 가비지 콜렉터에게 맡기면 되는 것인지, c/c++ 레벨에서 free / release 를 해주어야 하는 것인지 정확히 구분하기 어렵다.

NewIntArray() 의 경우는 생성된 배열을 return 시켜 java 레벨로 올려주므로 별도의 release 는 필요없을 것으로 생각된다.

그러나 SetIntArrayRegion() 에서 argument 로 들어가는 jint * 는 c/c++ 에서만 사용하므로,

malloc 을 했다면 반드시 free 를 해주어야 할 것이다.

 

* JNI 가 정확한 자료나 책이 많지 않기때문에, 경험상 android source 에서 reference 를 구하는 것이 가장 좋다.

 

==================================================================================