본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[Java] JNI Tutorial ( HelloJNI )

by 돼지왕 왕돼지 2012. 3. 24.
반응형



안녕하세요 돼지왕왕돼지입니다.
지금까지 JNI 에 대해 이론적으로 쌈빡하게 알아봤었죠?

2012/03/21 - [프로그래밍 놀이터/자바] - [Java] JNI 가 뭔가요? ( JNI Introduction )  
2012/03/21 - [프로그래밍 놀이터/자바] - [Java] JNI Design Overview. ( JNI 의 전체 구조 ) 
2012/03/22 - [프로그래밍 놀이터/자바] - [Java] JNI Type 과 Data Structure. 
2012/03/22 - [프로그래밍 놀이터/자바] - [Java] JNI functions. 
2012/03/22 - [프로그래밍 놀이터/자바] - [Java] JNI Invocation API.


오늘은 실질적으로 JNI 를 사용한 아주 간단한 앱. HelloJNI 를 만들어보겠습니다.

이 글은 http://java.sun.com/docs/books/jni/html/start.html#769 를 번역 및 정리한 글입니다.

HelloJNI

HelloJNI 는 Java Application 이 JNI 를 통해서 C 언어로 정의된 native function을 호출,  "Hello JNI!" 를 프린트하는 예제입니다. 다음은 이 예제 프로그램의 step을 보여줍니다.





Declare the Native Method


<HelloJNI.java>

class HelloJNI{

   private native void print();

   public static void main( String[] args ){

      new HelloJNI().print();

   }


   static{

      System.loadLibrary( "HelloJNI" );

   }

}

- 보통 static initializer 를 이용하여, native function 들을 implement 한 library 를 로드합니다.

- native function 은 native 라는 modifier 를 써서 정의합니다. 그리고 native function 정의는 구현부 없이 ; 로 마무리합니다.

- System.loadLibrary( "HelloJNI" ); 는 platform-dependent 한 구현을 보여주는데, Win32 에서는 HelloJNI.dll 로 mapping 되고 Solaris 에서는 libHelloJNI.so 로 mapping 됩니다.




Compile the HelloJNI Class


javac HelloJNI.java




Create the Native Method Header File


javah tool 을 이용해서 JNI-style header file 을 만듭니다. 이 header file 은 아시다시피 C 함수를 구현하는데 편리하게 사용되지요.


javah -jni HelloJNI


출력되는 파일은 HelloJNI.h 입니다. 생성된 헤더 파일 중 가장 중요한 부분은 function prototype 입니다.


<HelloJNI.h>

...
JNIEXPORT void JNICALL
Java_HelloJNI_print ( JNIEnv *, jobject ); 
... 


여기서 주목해서 봐야 할 부분은 argument 부분입니다. 첫번째 argument 로 전달되는 JNIEnv 는 JNI interface pointer 로 JNI function table 을 가르키고 있는 pointer 입니다. 두번째 argument 는 this에 해당하는 HelloJNI object 그 자신입니다. 




Write the Native Method implementation


javah 를 통해 만들어진 JNI-style header file은 native C, C++ code 를 짜는 데 좋습니다. native code 구현은 다음과 같습니다.


<HelloJNI.c>

#include <jni.h>

#include <stdio.h>

#include "HelloJNI.h"


JNIEXPORT void JNICALL

Java_HelloJNI_print( JNIEnv *env, jobject obj ){

   printf( "Hello JNI!\n" );

   return;

}


jni.h 헤더파일은 jni 에 사용되는 모든 코드에 load 되어야 합니다.




Compile the C Source and Create a Native Library


OS 마다 naive library 를 build 하는 방법이 다릅니다.

Solaris 에서는 다음의 command 를 통해 libHelloJNI.so 를 만듭니다.


cc -G -I/java/include -I/java/include/solaris HelloJNI.c -o libHelloJNI.so


-G option 은 C compiler 에게 일반 실행파일이 아닌 shared library 를 만든다는 것을 명시해주는 것입니다. 

 

Win32에서는 다음 명령을 통해 dynamic link library( DLL ) HelloJNI.dll 을 만듭니다.


cl -lc:\java\include -lc\java\include\win32 -MD -LD HelloJNI.c -FeHelloJNI.dll


-MD option 은 WIn32 multithread C library 와 link 되도록 만들어 줍니다. _LD 는 일반 실행파일이 아닌 DLL 을 만든다는 것을 알려줍니다 




Run the Program


이제 실행에 필요한 2개의 파일을 가지고 있습니다. 하나는 HelloJNI.class 이고 하나는 HelloJNI.dll 입니다. 


java HelloJNI


를 통해서 수행을 합니다. 간혹 java.lang.UnsatisfiedLinkError : no HelloJNI in library path 를 내뿜는 경우가 있습니다. 이 에러는 library path 가 맞지 않아서 그런 것인데, library path 는 Java VM이 미리 설정해 놓습니다.


Solaris system 에서는 LD_LIBRARY_PATH 환경 변수에 native library path 가 정의되어 있고, Win32 계열은 현재 directory 또는 PATH 환경 변수에 정의된 폴더를 참조합니다.


Java 2 SDK 1.2 부터는 java 실행명령에 libary path 를 명시할 수도 있습니다.


java -Djava.library.path =. HelloJNI


-D 옵션은 Java의 system property 를 설정한다는 의미이고, java.library.path를 .으로 설정한 것은 현재 폴더에서 library 를 검색한다는 의미입니다.




도움이 되셨다면 손가락 꾸욱~






반응형

댓글