java jni란?
jni는 Java Native Interface 입니다.
Java에서 native 코드로 작성된 라이브러리를 연계해줄 수 있는 기술입니다.
예를 들어, C나 C++같은 다른 코드로 작성된 라이브러리와 연계해주는 기술이라고 정의할 수 있습니다.
Java는 기본적으로 JVM위에서 실행되기에 특정운영체제에 종속적이지 않는데요,
모든 운영체제의 기능을 JVM에 담을 수 없기에 특정 OS의 기능을 실행하지 못하는 경우가 존재할 수 있습니다.
이처럼 Java로 구현하기 힘든 기능에 대해 Native Code (예를 들어 C나 C++로 작성된 dll이나 so파일)를 사용할 수 있도록 하게 해주는 기능입니다.
java코드에서는 native 키워드를 사용할 수 있으며, java 기본 라이브러리에서도 사용하고 있습니다.
예를 들어 아래와 같이 java.lang 에서도 사용하고 있는것을 확인할 수 있습니다.
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/ProcessHandleImpl.java
해당 java 클래스의 다른 메소드는 중괄호({})로 메소드의 body가 작성이 되어 있지만,
native 메소드를 보면 따로 body가 작성이 되어있지 않는것을 확인할 수 있습니다.
abstract 메소드나 java interface의 미구현 메소드가 아님에도 body가 없는 이유가
바로 native 키워드를 사용한 jni기술이 사용되었기 때문입니다.
이 메소드의 body는 외부 파일에 작성이 되어 있고, native function은 외부파일의 function 을 호출하는 것입니다.
이를 그림으로 표현하면 아래와 같이 표현할 수 있습니다.
java jni 를 사용하기 위한 개요
jni를 사용하기 위한 방식을 소개하려고 하는데요,
아래와 같은 최종 구조로 예제를 소개해드리려고 합니다.
jni를 사용하기 위한 방식은 아래와 같이 진행하면됩니다.
A. java 코드 작성
B. native 코드를 작성하기 위한 header 파일 생성
C. c파일 작성후 빌드
D. java 코드 빌드후 실행
각 스텝별 상세 설명은 아래에 설명합니다.
A. java 코드 작성
HelloWorldJNI.java 파일을 만들어줍니다.
파일 내용은 아래와 같이 native function이 들어간 코드를 작성해주고,
loadLibrary 메소드로 외부 라이브러리를 로드해줍니다.
1 | public class HelloWorldJNI { |
B. native 코드를 작성하기 위한 header 파일 생성
HelloWorldJNI.java 파일을 작성한 뒤, 커맨드창에 아래와 같이 입력해줍니다.
1 | javac -h . HelloWorldJNI.java |
그러면 아래와 같이 .h와 .class 파일 두개가 생긴것을 확인할 수 있습니다.
HelloWorldJNI.h
HelloWorldJNI.class
C. c파일 작성후 빌드
앞서 만든 HelloWorldJNI.h 파일 내용을 보면 아래와 같습니다.
1 | /* DO NOT EDIT THIS FILE - it is machine generated */ |
이 중 Java_HelloWorldJNI_sayHello에 대해 함수 내용을 작성해보겠습니다.
HelloWorldJNI.c 파일을 만들고, 아래와 같이 작성합니다.
1 | #include <stdio.h> |
그리고 아래와 같은 명령어로 공유 라이브러리 파일을 컴파일합니다. (리눅스의 경우)
1 | gcc -I${JAVA_HOME}/include -shared HelloWorldJNI.c -o HelloWorldJNI.so |
windows의 경우, 보통 visual studio 를 많이 쓰실텐데요,
developer command prompt for vs 또는 개발자 명령 프롬프트를 여시고,
아래와 같은 명령어로 빌드하면됩니다.
이 때, 64비트용(x64)으로 열어주셔야 나중에 java에서 호출 할 수 있습니다.
(32비트용으로 하실거면 java도 32비트용으로 빌드해주셔야 합니다. )
1 | cl.exe /LD /EHsc /I "%JAVA_HOME%\include" /I "%JAVA_HOME%\include\win32" HelloWorldJNI.c |
만일 아래와 같은 에러 발생시, JAVA_HOME이 환경변수로 등록되어있는지 확인해주세요.
1 | fatal error C1083: 포함 파일을 열 수 없습니다. 'jni.h': No such file or directory |
만일 developer command prompt for vs를 못 찾으실 경우 커맨드창으로 들어가신 후, 아래와 같은 명령어로 실행하시면 됩니다.
1 | {visual studio 설치 경로}\VC\Auxiliary\Build\vcvars64.bat |
그러면 아래와 같이 HelloWorldJNI.dll 파일이 생성된 것을 확인할 수 있습니다.
D. java 코드 빌드후 실행
앞서 컴바일된 HelloWorldJNI.dll 파일이나 HelloWorldJNI.so파일을 java코드가 있는 곳으로 옮깁니다.
HelloWorldJNI.java 에서 이름이 native인 라이브러리를 불러온다고 했으므로,
아래와 같이 파일명을 바꿔줍니다.
1 | HelloWorldJNI.dll -> native.dll |
아래와 같이 컴파일 한 후,
1 | javac HelloWorldJNI.java |
아래와 같이 실행을 해주면, 공유 라이브러리를 사용하여 프로그램이 실행된 것을 확인할 수 있습니다.
1 | java HelloWorldJNI -Djava.library.path="." |
총평
최근 JNI를 사용할 일이 있었는데, 어떻게 만들어지는지 궁금해서 찾아보게 되었습니다.
먼 옛날 리눅스에서는 사용해본적이 있었던거 같은데,
윈도에서 jni 를 사용하는 방법은 이번 기회에 처음 해보게 되었습니다.
가장 힘들었던것은 visual studio 사용하지 않고 c 파일을 컴파일하는 것이였습니다.
확실히 윈도에서 c언어 개발하려면 visual studio 를 써야 편한거 같네요.
많은 개발자들이 리눅스에서 개발을 많이 하셔서 그런지 윈도는 관련 자료찾기가 어려웠었는데,
이번 포스팅이 다른 분께도 도움이 되었으면 좋겠습니다.