JNI 동작 구조

JNI 개요

JNI(Java Native Interface)는 java로 만들어진 프로그램에서 해당 플랫폼에서만 실행 가능한 Native code에 접근하기 위해 만들어진 응용 프로그램의 인터페이스(API)입니다.

기존 C/C++(Native)로 구성된 프로그램을 Java에서 바로 사용할 수 있는 장점을 가지고 있습니다.

java 모듈 & C/C++ 상호작용

Java 모듈과 C/C++ 모듈은 서로 상호 작용을 합니다.

Java 모듈에서 C/C++ 모듈을 호출하고 C/C++ 모듈에서 Java 모듈을 호출합니다.

System.loadLibrary()가 실행되면 ART(Android Runtime)은 해당 이름의 공유 라이브러리를 로딩한 후 함수 심볼 검색을 합니다.

JNI 동작 구조

JNI Native 함수 등록 및 실행 - 자동매핑

로딩한 라이브러리에서 심볼을 검색한 후 JNI_OnLoad()함수가 구현되어 있는지 확인합니다.

JNI_OnLoad()함수가 없으면 DVM은 자동으로 라이브러리 내에 JNI Native 함수 심볼을 비교해 매핑 작업을 수행합니다.

Android Framework처럼 Native를 포함한 Java Class가 많은 경우 ART에서 라이브러리를 로딩하고 심볼을 일일이 검색해 매핑하는 작업은 성능 저하의 원인이 될 수 있습니다.

자동으로 연결작업을 수행하기 위해서는 Native Layer의 함수를

JNIEXPORT <리턴 타입> JNICALL java_<패키지명>_<클래스명>_<네이티브함수명>으로 수정해야 합니다.

JNI 함수명

javah를 이용하면 JAVA 파일을 빌드하여 얻은 class파일로 부터 JNI 규약에 맞는 헤더파일을 얻을 수 있습니다.

1
2
3
4
5
package com.example
class Helloworld {
private native void print();
}
static System.loadLibrary("HelloWorld");
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
1
2
//JNIEXPORT <리턴 타입> JNICALL java_<패키지명>_<클래스명>_<네이티브함수명>
JNIEXPORT void JNICALL Java_com_example_HelloWorld_print(JNIEnv *env, jobject thiz){ }

JNI Native 함수 등록 및 실행 - 수동매핑

로딩한 라이브러리에서 심볼을 검색한 후 JNI_OnLoad()함수가 구현되어 있는지 확인하고 해당 함수가 포함되어 있으면 자동으로 호출합니다.

RegisterNative()함수를 사용해서 ART에서 자동으로 라이브러리 내에 JNI Native함수 심볼을 비교하여 연결해 주는 작업 대신 프로그래머가 직접 연결 작업을 처리하기 때문에 로딩 속도를 향상시킬 수 있습니다.

연결방법은 아래와 같습니다.

① Application or Application Framwork

1
2
Syatme.loadLibrary("android_servers")
nativeInit();

② libandroid_servers.so → JNI_OnLoad() 실행 → RegisterNatives() 매핑 수행

1
2
3
4
static JNINativeMethod gMethods[] = {
/* name(자바함수), signature(리턴타입), funcPtr(c/c++함수) */
{ "nativeInit", "()V", (void*)android_server_SystemServer_nativeInit},
};
공유하기