0%

java jni란?, jni 사용하기, windows에서 jni사용하기, 윈도jni

jni

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

jni

해당 java 클래스의 다른 메소드는 중괄호({})로 메소드의 body가 작성이 되어 있지만,
native 메소드를 보면 따로 body가 작성이 되어있지 않는것을 확인할 수 있습니다.
abstract 메소드나 java interface의 미구현 메소드가 아님에도 body가 없는 이유가
바로 native 키워드를 사용한 jni기술이 사용되었기 때문입니다.
이 메소드의 body는 외부 파일에 작성이 되어 있고, native function은 외부파일의 function 을 호출하는 것입니다.

이를 그림으로 표현하면 아래와 같이 표현할 수 있습니다.
jni

java jni 를 사용하기 위한 개요

jni를 사용하기 위한 방식을 소개하려고 하는데요,
아래와 같은 최종 구조로 예제를 소개해드리려고 합니다.

jni

@startuml

node “HelloWorldJNI.class” as A {
node “native void sayHello()” as CC
}

node “JNITest.dll” as B {
node “sayHello()” as DD
}
CC -> DD

@enduml

jni를 사용하기 위한 방식은 아래와 같이 진행하면됩니다.
A. java 코드 작성
B. native 코드를 작성하기 위한 header 파일 생성
C. c파일 작성후 빌드
D. java 코드 빌드후 실행

각 스텝별 상세 설명은 아래에 설명합니다.

A. java 코드 작성

HelloWorldJNI.java 파일을 만들어줍니다.
파일 내용은 아래와 같이 native function이 들어간 코드를 작성해주고,
loadLibrary 메소드로 외부 라이브러리를 로드해줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloWorldJNI {

static {
System.loadLibrary("native");
}

public static void main(String[] args) {
(new HelloWorldJNI()).sayHello();
}

private native void sayHello();
}

B. native 코드를 작성하기 위한 header 파일 생성

HelloWorldJNI.java 파일을 작성한 뒤, 커맨드창에 아래와 같이 입력해줍니다.

1
javac -h . HelloWorldJNI.java

그러면 아래와 같이 .h와 .class 파일 두개가 생긴것을 확인할 수 있습니다.

HelloWorldJNI.h
HelloWorldJNI.class
jni

C. c파일 작성후 빌드

앞서 만든 HelloWorldJNI.h 파일 내용을 보면 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorldJNI */

#ifndef _Included_HelloWorldJNI
#define _Included_HelloWorldJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorldJNI
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorldJNI_sayHello
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

이 중 Java_HelloWorldJNI_sayHello에 대해 함수 내용을 작성해보겠습니다.
HelloWorldJNI.c 파일을 만들고, 아래와 같이 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
 #include <stdio.h>
#include "HelloWorldJNI.h"

JNIEXPORT void JNICALL Java_HelloWorldJNI_sayHello
(JNIEnv *env, jclass obj)
{
printf("Hello World!\n");
return;
}


그리고 아래와 같은 명령어로 공유 라이브러리 파일을 컴파일합니다. (리눅스의 경우)

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

jni

만일 아래와 같은 에러 발생시, JAVA_HOME이 환경변수로 등록되어있는지 확인해주세요.

1
fatal error C1083: 포함 파일을 열 수 없습니다. 'jni.h': No such file or directory

만일 developer command prompt for vs를 못 찾으실 경우 커맨드창으로 들어가신 후, 아래와 같은 명령어로 실행하시면 됩니다.

1
2
3
{visual studio 설치 경로}\VC\Auxiliary\Build\vcvars64.bat 
{visual studio 설치 경로}\VC\Tools\MSVC\14.40.33807\bin\Hostx64\x64\cl /LD /EHsc /I "%JAVA_HOME%\include" /I "%JAVA_HOME%\include\win32" HelloWorldJNI.c

그러면 아래와 같이 HelloWorldJNI.dll 파일이 생성된 것을 확인할 수 있습니다.
jni

D. java 코드 빌드후 실행

앞서 컴바일된 HelloWorldJNI.dll 파일이나 HelloWorldJNI.so파일을 java코드가 있는 곳으로 옮깁니다.
HelloWorldJNI.java 에서 이름이 native인 라이브러리를 불러온다고 했으므로,
아래와 같이 파일명을 바꿔줍니다.

1
2
HelloWorldJNI.dll -> native.dll
HelloWorldJNI.so -> native.so

아래와 같이 컴파일 한 후,

1
javac HelloWorldJNI.java

아래와 같이 실행을 해주면, 공유 라이브러리를 사용하여 프로그램이 실행된 것을 확인할 수 있습니다.

1
java  HelloWorldJNI -Djava.library.path="."

jni

총평

최근 JNI를 사용할 일이 있었는데, 어떻게 만들어지는지 궁금해서 찾아보게 되었습니다.
먼 옛날 리눅스에서는 사용해본적이 있었던거 같은데,
윈도에서 jni 를 사용하는 방법은 이번 기회에 처음 해보게 되었습니다.
가장 힘들었던것은 visual studio 사용하지 않고 c 파일을 컴파일하는 것이였습니다.
확실히 윈도에서 c언어 개발하려면 visual studio 를 써야 편한거 같네요.
많은 개발자들이 리눅스에서 개발을 많이 하셔서 그런지 윈도는 관련 자료찾기가 어려웠었는데,
이번 포스팅이 다른 분께도 도움이 되었으면 좋겠습니다.