개인적으로 Android 쪽 개발을 하면서 가장 많이 사용한 부분이 JNI 입니다...


그러나 JNI 문법이 생각보다 까다롭고, 헛갈리는 경우가 많아서...


예제 코드 없이 바로 구현하기는 어려운 경우가 많이 있습니다...


앞으로 회사에서 필요한 경우도 생길 수 있을 것같고, 개인적으로 정리도 할 겸...


JNI programming 에 대한 내용을 조금씩 올려보도록 하겠습니다...


===== (1) hello, world ! ============================================================


1. JNI 란 ?


java native interface 의 약자로 VM 위에서 실행되는 java 프로그램에서 해당 플랫폼의 native code 에 접근할 수 있도록하는 interface 를 말합니다. 주로 c/c++ 로 구현되어 build 된 동적 라이브러리 - so, dll - 와 연동하기 위해 사용됩니다.


2. Java 구현.


- Hello.java : HelloJNI 의 native 함수 printHello() 를 호출하는 main class


public class Hello {

        public static void main(String[] args) {

                HelloJNI.printHello();

        }


- HelloJNI.java : native 함수가 선언된 class, 반드시 static 영역에 loadLibrary() 를 호출해서 class 접근시 library(so) 가 load 되도록 한다.


public class HelloJNI {

        static {

                System.loadLibrary("mylib");

        }

        public static native void printHello();


- java compile


$ javac HelloJNI.java

$ javac Hello.java



3. c library 구현.


- JNI header 생성


$ javah -jni HelloJNI 


위의 명령을 실행하고 나면 "HelloJNI.h" 가 생성되는 것을 확인할 수 있다.


- HelloJNI.h


/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class HelloJNI */


#ifndef _Included_HelloJNI

#define _Included_HelloJNI

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     HelloJNI

 * Method:    printHello

 * Signature: ()V

 */

JNIEXPORT void JNICALL Java_HelloJNI_printHello

  (JNIEnv *, jclass);


#ifdef __cplusplus

}

#endif

#endif 


"HelloJNI.h" 에 해당 class 의 native 함수 - printHello - 에 대한 선언이 되어있음을 알 수 있다. 규칙 익숙해지면 javah 의 도움없이 native 함수의 선언을 할 수 있고, onload 함수를 이용해서 등록하는 방법도 있다.


- HelloJNI.c


#include "HelloJNI.h"

#include <stdio.h>


JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject obj)

{

        printf("Hello, world !\n");


HelloJNI.h 에 선언된 Java_HelloJNI_printHello 함수를 구현한다.


- library build


$ gcc -shared -o libmylib.so HelloJNI.c -I/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java-6-openjdk/include/linux/ 


동적 library 로 빌드함므로 -shared, "jni.h" 에 해당하는 include directory 를 추가해준다.

build 하는 ubuntu PC 에 openjdk 가 설치되어 있어야 한다. ( # apt-get install openjdk-6-jdk )


4. 실행


이제 libmylib.so 를 java "HelloJNI" class 에서 native 함수로 불러서 실행할 수 있다.

library 가 load 될 때 찾을 수 있도록 LD_LIBRARY_PATH 를 추가한다.


$ export LD_LIBRARY_PATH=./ 

$ java Hello

Hello, world !


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


간단한 hello, world 를 찍는데도 절차가 꽤 복잡한 것같다.

하지만 개발 환경이 어느 정도 구축되면 그렇게 복잡하지만은 않다.