JNI와 NDK (2) JNI의 기본 원리
by Sihyeon Kim
최종 수정일 : 2019-03-29
JNI 기본 원리 이해 - 예제 프로그램
- 예제 프로그램 : C 함수를 호출하는 간단한 자바 프로그램
- 예제 프로그램 개발 순서 (JNI를 이용해서 개발할 때는 대부분 예제 프로그램과 동일한 절차를 밟는다.)
(1) 자바 코드 작성
(2) 자바 코드 컴파일
(3) C 헤더 파일 생성
(4) C 코드 작성
(5) C 공유 라이브러리 생성
(6) 자바 프로그램 실행
(1) 자바 코드 작성
- C함수를 호출할 수 있는 자바 코드 HelloJNI.java 작성
- 네이티브 메서드 : 자바 메서드, 실제로 자바가 아닌 C/C++ 같은 네이티브 언어로 작성된 함수
(약속) - JNI 구현에서 메서드 선언은 자바 코드에서, 선언된 메서드의 실제 구현은 C/C++ 코드에서 이루어진다.
이 책에서는 자바에서 선언된 메서드를 네이티브 메서드, C/C++ 코드로 구현된 함수를 JNI 네이티브 함수라고 부른다.
(2) 자바 코드 컴파일
(3) C/C++ 헤더 파일 생성
- 자바 가상 머신은 자바 클래스 내부에 선언된 네이티브 메서드와 매핑할 C 함수를 로드된 라이브러리에서 찾아 매핑 테이블 형태로 만들어 놓는다. 그러고 나면 자바 네이티브 메서드와 C 함수가 링크된다.
-
자바 가상 머신은 일반적인 형식의 C 함수를 자바 네이티브 메서드와 직접 매핑하지 않는다.
- 자바 가상 머신은 네이티브 라이브러리를 로딩하면서 해당 라이브러리에 들어 있는 C 함수 가운데 어떤 함수가 자바 코드의 네이티브 메서드와 매핑될지 어떻게 식별할 수 있을까?
- 함수 형태로 식별한다.
- JNI 명세에서 정한 대로 함수 원형을 작성하면 자바 가상 머신은 해당 함수가 네이티브 메서드와 매핑될 함수라고 식별하게 한다.
- JNI 명세에 나온 대로 함수 원형을 만드는 작업을 도와주는 것이 javah라는 툴이다. 이 툴은
\bin에 포함돼 있다. 자바 네이티브 메서드와 연결될 수 있는 C 함수의 원형을 생성해준다. - 사용법은 아래와 같다.
javah <native로 선언된 메서드를 포함한 자바 클래스 이름>
- javah를 통해 출력되는 결과물은 입력 인자로 넘긴 자바 클래스 이름과 동일한 C언어 헤더 파일이다. 이 파일에는 javah의 입력 인자로 넘긴 자바 클래스의 네이티브 메서드와 JNI와 연결할 수 있는 C 함수의 원형이 정의돼 있다.
- HelloJNI.h 파일에는 HelloJNI 클래스의 네이티브 메서드에 대한 C 함수의 원형이 들어간다.
- javah에 의해 생성된 헤더 파일의 함수 이름
JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *, jobejct)
반환타입 접두사 클래스이름 네이티브 메서드 이름 공통 매개변수
- JNI 네이티브 함수가 어떤 자바 클래스의 어떤 네이티브 메서드와 매핑되어 있는지 알 수 있다.
-
위의 예는 HelloJNI 클래스의 printHello() 네이티브 메서드와 연결되는 함수 원형이다.
- javah가 생성하는 함수 원형의 매개변수
- 첫 번째 두번째 매개변수로
JNIEnv *
와jobject
라는 디폴트 매개변수가 포함되어 있다. - JNI를 지원하는 함수는 이 두개의 공통 매개변수를 반드시 포함해야 한다.
- 첫 번째 매개 변수
JNIEnv *
: JNI 인터페이스 포인터, 이 포인터를 통해 JNI 명세에 포함된 다양한 JNI 함수를 호출할 수 있다.
(JNI 함수 : JNI 네이티브 함수가 아님. JNI 네이티브 함수에서 자바의 객체를 생성하거나 메서드를 호출하는 등의 일을 할 수 있게 JNI에서 기본적으로 제공하는 함수 모음) - 두 번째 매개 변수 타입
jobject
: JNI에서 제공되는 자바 네이티브 타입, C 코드에서 자바 객체에 접근할 때 쓰인다. 이 매개변수에는 네이티브 메서드를 호출한 객체의 레퍼런스 값이 전달된다. 예에서 myJNI 객체의 레퍼런스 값이 전달된다. - 세 번째 매개 변수부터는 네이티브 메서드가 가지는 매개변수 타입과 비슷한 형태로 C 함수의 매개 변수가 각각 생성된다.
- printString(String str)에는 String 타입 매개변수가 있으므로 C 함수에 jstring 타입의 매개변수가 하나 더 추가된다.
- 첫 번째 두번째 매개변수로
- (참고) 자바 네이티브 타입
- 자바는 플랫폼 독립적이므로 자바의 데이터 타입은 어떤 플랫폼에서든 메모리 크기가 동일하다.
- 예를 들어 자바 int 타입은 모든 플랫폼에서 크기가 4바이트이다.
- 하지만 C/C++ 같은 네이티브 언어에서는 동일한 데이터 타입이더라도 플랫폼에 따라 크기가 달라질 수 있다.
- JNI 프로그래밍에서 자바 프로그램과 C/C++ 함수 사이의 데이터 교환이 자주 일어난다. 이때 두언어 사이에서 데이터 타입이 서로 통일되지 않는다면 프로그램의 정상 동작 여부를 보장할 수 없다.
- JNI는 C/C++ 같은 네이티브 언어에서도 자바의 데이터 타입을 사용할 수 있게끔 자바 네이티브 타입을 제공한다.
- JNI 프로그래밍을 하는 C/C++ 개발자들은 자바 코드에서 데이터(인자, 함수 반환 값)를 보내거나 받을 때 자바 네이티브 타입을 사용하면 된다.
jni.h 와 jni_md.h 파일에 자바 네이티브 타입이 정의돼 있다. - 자바의 클래스, 객체 등과 같은 레퍼런스 타입에 대해서도 자바 네이티브 타입이 제공된다.
- jni 명세 http://java.sun.com/docs/books/jni/
(4) C/C++ 코드 구현
(5) C 공유 라이브러리 생성
3단계 4단계에서 작성한 헤더 파일과 소스 파일을 가지고 공유 라이브러리를 만든다.
microsoft visual studio 를 이용해 코드를 빌드하고 라이브러리를 만들어 보자.
(6) 자바 프로그램 실행
Subscribe via RSS