본문 바로가기

Software/JAVA

(이전글 2006년) JNI

반응형

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. C/C++ 작성



#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
 
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj) {
      printf("Hello World!!\n");
}

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



8. gcc HelloWorld.c -o lib/libHelloWorld.so -shared -I /usr/java/include -I /usr/java/include/linux


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


9. java HelloWorld


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


주의사항 한가지 더!!


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

 

 

참고 사이트: http://java.sun.com/docs/books/tutorial/native1.1/index.html

반응형