SSISO Community

시소당

JNI - Java Native Interface 사용하기

JAVA라는  언어가  플렛폼  독립적임을  추구함으로써  생기는  커다란  장점  뒤에는  특정  플렛폼에  종속적인  기능을  수행하지  못한다는  관점에  따라선  커다란  단점이  있다.  이를  해결하기  위한  해결책이  JNI  -  Java  Native  Interface  이다.  JNI  는  JAVA로부터  C/C++을  호출할  수  있도록  해준다.

JAVA가  JVM을  통해  해석되어  실행되는  메커니즘  때문에  잃는  속도를  JNI로  충당할  수  있다고  말하는  사람도  있다.  그러나  적어도  내  주관적인  의견으로는  단지  속도  문제가  거슬려서  JNI를  이용하는  것은  부적절한  행동이라  생각한다.

그렇다면  왜  나는  JNI를  서술하고  있는가?  JNI의  주된  용도는  레거시  시스템과의  연동과  플렛폼  종속적인  기능의  사용에  있다.  리눅스가  설치된  컴퓨터에  모터가  달려있고  이것을  제어하기  위한  드라이버가  C  API만  제공한다면  JAVA를  이용하는  개발자는  JNI가  필수적이다.  지금  말한  이것이  내가  JNI를  서술하고  있는  이유이다.

리눅스에서의  JNI  사용  튜토리얼

1.  mkdir  JNI/lib
2.  cd  JNI
3.  export  LD_LIBRARY_PATH=`pwd`/lib

LD_LIBRARY_PATH가  설정되어있지  않으면  컴파일된  JAVA  클래스의  실행시  native  호출  대상을  찾을  수  없어서  System.loadLibrary()  에서  예외가  발생한다.

4.  java  클래스  작성

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

        public  native  void  printHelloWorld();

        public  static  void  main(String[]  args)  {
                  new  HelloWorld().print();
        }
}

System.loadLibrary()  를  통해  JNI로  연동할  so  파일명을  서술한다.  static  블럭으로  설정해야한다.  C/C++로  구현한  함수의  호출은  native  키워드를  사용해  정의한다.

5.  java  클래스  컴파일  (저  상태로  컴파일에  전혀  문제가  없다)
6.  javah  -jni  HelloWorld

C/C++  을  위한  헤더  파일을  생성한다.  javah  뒤에  컴파일된  클래스가  와야하므로  컴파일이  먼저고  헤더  생성이  다음이다.

7.  6에서  생성한  헤더를  구현:  C/C++  코드  작성

#include  <JNI.H>
#include  <STDIO.H>
#include  "HelloWorld.h"

JNIEXPORT  void  JNICALL  Java_HelloWorld_print(JNIEnv  *env,  jobject  obj)  {
        printf("Hello  World!!");
}

6번에서  생성된  헤더  파일을  보면  C/C++에서  작성해야  할  함수의  원형이  정의되어있다.  거기에  맞춰  함수를  작성한다.  인자로  넘어오는  JNIEnv와  jobject에  대해선  여기서  언급하지  않는다.

8.  7에서  생성한  코드  컴파일:  gcc  HelloWorld.c  -o  lib/libHelloWorld.so  -shared  -I  /usr/java/include  -I  /usr/java/include/linux

작성된  C/C++을  컴파일한다.  주의할  점은  '-I  '  소문자  '엘'이  아니라  대문자  '아이'다.  또한  생성할  오브젝트  파일의  이름  앞에  'lib'를  붙여야한다.  (플렛폼마다  다를  수  있음)

9.  java  클래스  실행:  java  HelloWorld

System.loadLibrary(이름)  는  LD_LIBRARY_PATH에서  이름.so  를  찾는  듯  하다.  따라서  LD_LIBRARY_PATH  가  잘못  정의되어있거나  so파일  이름이  명시된  이름과  다르면  실행시  예외가  발생한다.


주의사항!!
자  바의  패키지  정보가  변동되어선  안된다.  예를들어  새로운  JAVA  프로그램에서  JNI  연동을  할  경우  만약  그  프로그램이  package  common;  을  선언하고  그  안에서  System.loadLibrary("HelloWorld")  를  호출했다면  그  자체의  호출엔  문제가  없으나  라이브러리  함수를  호출하는  시점에서  런타임  에러가  날  것이다.  이  경우  5번부터  다시  작업해야한다.

참고  사이트:  http://java.sun.com/docs/books/tutorial/native1.1/index.html  
출처  :  http://java-project.tistory.com/2

654 view

4.0 stars