2016년 12월 14일 수요일

[JNI] Java JNI 연동 방법

Java에서 C쪽 레거시 연동을 위해서 JNI를 사용할 때가 있습니다.
이때 연동하는 절차에 대해서 간단하게 정리해 봤습니다.

1. java 에서 호출 하기

public class Hello {
    native void helloFromC(int iValue, String sValue);
    static {
        System.loadLibrary("chello");
    }
    static public void main(String argv[]) {

        int i = 1;
        String s = "testval";
        Hello helloWorld = new Hello();
        helloWorld.helloFromC(i, s);
    }
}

native 로 C쪽에서 사용할 메소드를 선언합니다.
그리고  System.loadLibrary  로 C 소스를 로딩합니다.
마지막으로  호출해서 사용합니다.

2. java 소스 컴파일 및 C에서 사용할 소스의 헤더 생성하기

일단 javac 로 자바 파일을 컴파일 한 후에 javah 로 c에서 사용할 헤더파일을 생성합니다.

$ javac Hello.java
$ javah Hello

3. c 코드 작성하기 

#include "Hello.h"

JNIEXPORT void JNICALL Java_Hello_helloFromC
  (JNIEnv * env, jobject jobj, jint ival, jstring sval)
{
 const char *name = (*env)->GetStringUTFChars(env, sval, NULL);
     printf("Hello from C!\n");
     printf("%d ____ %s \n",ival,name);
     
     printf("Hello from C exit\n");     
}

4. c 코드 컴파일 하기

$ gcc -o libchello.so -shared chello.c -lc -fPIC

* 참조하는 라이브러리가 있는경우 아래와 같이 참조를 해서 컴파일 한다.
$ gcc -o libchello.so -shared -I/home/temp/Stat_Test -I/home/FRAMEWORK/include chello.c -lc -fPIC -L/home/FRAMEWORK/lib/ -lstctl


5. 실행한다. 

$ java Hello

실행시 다음과 같은 에러가 나는 경우가 있습니다.
이런 경우는 64bit 로 컴파일하고 32bit JDK 버젼에서 실행한 경우이다. 

$ /usr/local/j2sdk1.4.2_19/bin/java Hello
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/temp/TT/libchello.so: /home/temp/TT/libchello.so: wrong ELF class: ELFCLASS64 at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1586) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1511) at java.lang.Runtime.loadLibrary0(Runtime.java:788) at java.lang.System.loadLibrary(System.java:834) at Hello.(Hello.java:4)

* 주의 사항 : 테스트는 패스를 숨기기위해서 일부 경로 정보를 조작한게 있습니다.
(무조건 복붙해서 돌리면 에러가 날 수도 있다는 뜻입니다.)
* 주의 사항 : 테스트는 같은 폴더에 있어서 패스 설정하는 부분이 빠져 있습니다.
* 주의 사항 : 실제 Web 서버에서 사용할때는 라이브러리가 LD_LIBRARY 패스에 들어가 있어야 합니다.

댓글 없음:

댓글 쓰기