시냅스

JNI, Java의 Native Code 사용 설명 및 예제 본문

Java, Spring

JNI, Java의 Native Code 사용 설명 및 예제

ted k 2023. 3. 5. 17:38

JNI

  • C/C++ 등의 네이티브 언어로 작성된 코드와 상호작용할 수 있도록 하는 프로그래밍 인터페이스
  • JNI를 통해 네이티브 언어와 함수 호출 및 데이터 전달이 가능하게 한다.
    • 메시지 및 자바 객체
  • 하드웨어 제어를 쉽게할 수 있게 한다.
  • DLL 을 사용한다.
    • DLL은 라이브러리에 대한 linking 만 해 두었다가
    • 특정 메모리영역을 할당 받아서 필요한 내용만 loading 한다.
    • 또한 특정 메모리 영역은 프로세스 간에 공유가 가능하다.
    • 바이트 코드와 네이티브 코드를 동일한 바이너리 파일에 혼합할 수 없기 때문에 독립적으로 컴파일 / 실행 (JVM / GCC(or else)) 하고 메시지를 주고 받는다.
  • 사용할 함수를 native 키워드를 통해 선언하고
  • 가져올 DLL 을 static block 에 선언한다.

https://liltdevs.tistory.com/91

 

주메모리의 관리 Main Memory

주메모리의 관리, Main Memory memory에 Load된 program -> process 메모리는 바이트로 이뤄진 주소를 배열로 한다. PC(Programcounter) -> 주소 -> 명령어, 필요하면 더 데이터를 더 가져오거나 내보낼 수도 있다.

liltdevs.tistory.com

 

구현 예제

public class Sample {
    static {
        System.loadLibrary("sample");
    }

    private native void print(String message);

    public static void main(String[] args) {
        Sample sample = new Sample();
        sample.print("Hello, JNI!");
    }
}
  • java로 전달한 메세지를 print 하는 간단한 소스를 만들어 준다.

 

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Sample */

#ifndef _Included_Sample
#define _Included_Sample
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Sample
 * Method:    print
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_Sample_print(JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
  • 위와 같이 header file 이 생성되고

 

#include "sample.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_Sample_print(JNIEnv *env, jobject obj, jstring message) {
    const char *msg = (*env)->GetStringUTFChars(env, message, NULL);
    printf("%s\\n", msg);
    (*env)->ReleaseStringUTFChars(env, message, msg);
}
  • 맞춰서 실행하는 함수를 작성한다.

 

$ gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin/" -o libSample.jnilib -shared sample.c
  • 위와 같이 컴파일 하면 libSample.jnilib 파일이 생성된다.
  • 이제 클래스를 실행하면 원하는 문자열이 출력된다.
Comments