Burt.K

코코아를 좋아하는 프로그래머입니다 ;)

HelloJNI

맥에서 Hello JNI!를 출력하는 자바 응용프로그램을 개발해 보자. 단 이 응용프로그램은 문자열을 출력하는 부분을 C++ 로 작성할 것이다.

네이티브 라이브러를 사용하는 자바 클래스 작성하기

  • 더 편하게 읽기 : http://skyfe79.gitbooks.io/jni-tutorial/content/chapter1.html
  • $ vi HelloJNI.java
    // 주의! 학습 편의를 위해서 패키지를 작성하지 않는다!
    
    class HelloJNI {
        private native void print();
        public static void main(String[] args) {
            new HelloJNI().print();
        }
        static {
            System.loadLibrary("HelloJNI");
        }
    }

    자바 코드 파일을 컴파일하여 class파일을 만든다.

    $ javac HelloJNI.java

    JNI C++ 파일을 만들기 위해서 javah를 이용해 C++ 헤더파일을 만든다.

    $ javah -jni HelloJNI

    만들어진 파일을 확인해 보자

    $ cat HelloJNI.h
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class HelloWorld */
     
    #ifndef _Included_HelloJNI
    #define _Included_HelloJNI
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     HelloJNI
     * Method:    print
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_HelloJNI_print
      (JNIEnv *, jobject);
     
    #ifdef __cplusplus
    }
    #endif
    #endif

    JNI 함수명과 인자타입 등은 관련 문서를 참고한다.

    Java_HelloJNI_print 함수를 작성한다.

    $ vi HelloJNI.cpp
    #include <jni.h>
    #include <iostream>
    #include "HelloJNI.h"
     
    JNIEXPORT void JNICALL Java_HelloJNI_print
    (
        JNIEnv  *env, 
        jobject  thiz
    )
    {
        std::cout << "Hello JNI!" << std::endl;
    }

    HelloJNI 네이티브 라이브러리를 만들기 위해서는 jni.h 파일의 위치를 알아야 한다. 맥에서는 아래의 위치에 있다.

    $ ls /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/

    컴파일해 보자

    $ g++ "-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/" -c HelloJNI.cpp

    컴파일하면 HelloJNI.o 파일이 생성된다. 이제 동적라이브러리를 생성한다. 주의할 점은 라이브러리명은 반드시 lib으로 시작해야 하고 확장자는 jnilib 이여야 한다. 위 컴파일문에서 jni.h를 찾을 수 없다는 오류가 발생하면 jni.h 가 있는 곳을 찾아서 적어줘야 한다. 아래처럼 심볼링 링크를 직접 만들어서 사용해야 한다. 예를 들어 /System/Library/Java/JavaVirtualMachines/Headers 폴더를 만든 후 해당 폴더로 이동한 다음 아래의 명령어를 실행한다.

    $ sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h jni.h
    $ ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni_md.h jni_md.h
    $ g++ -dynamiclib -o libhellojni.jnilib HelloJNI.o

    실행한다

    $ java HelloJNI
    Hello JNI!

    만약 아래와 같은 링크 오류가 발생하면 실행할 때 네이티브 라이브러리가 있는 위치를 설정해야 한다.

    Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloJNI in java.library.path
    $ java -Djava.library.path="." HelloJNI
    ← JNI 튜토리얼
    Swift에 Go언어의 장점을 더해보자 →