현재 안드로이드 플랫폼에 네이티브 라이브러리를 포팅해보고 있다.
그러면서 팀내에 JNI 사용에 관련된 개선을 위해 안드로이드 전체 소스를 보면서 JNI을 어떻게 사용한지 보고 따라하면서 개선을 해보았다. 그러면서 우연히 인사이드 안드로이드 책을 보면서 공감하며 다시한번 그내용을 정리해보았다.
- 재화 2010.10.22
1. 기본적인 JNI 사용하는 방법
우선 위 내용을 생략한다. 위 문서는 우선 기본적인 JNI 를 사용할 수 있는 독자임을 가정한다. JNI 기본적인 사용은 안드로이드 NDK 기본 샘플을 통해서 충분히 읽힐 수 있다. 아래의 방법은 NDK 에서 기본 샘플로 제공하지 않은 방법이다.
2. JNI 네이티브 함수를 직접 등록 하는 방법
A. 문제점 - 첫번째 방안(기본적인 JNI 사용하는 방법) 의 문제점
소수의 메서드를 JNI를 통해 사용한다면 자바가상머신(JVM)이 메서드를 자동으로 JNI 네이티브 매핑하는데에는 오래 걸리지 않는다. 하지만 안드로이드 프레임웍이나 복잡한 라이브러리(ex.libEmailCore.so)와 같이 네이티브 메서드를 사용하는 자바클래스가 많을 경우에는 자바가상머신이 라이브러리를 로딩하고 이들의 심볼을 검색하여 각 네이티브 메서드를 자바 클래스의 메서드와 연결하는 작업은 분명 성능 저하의 원인이 된다.
B. 해결안
JNI 는 위 문제의 해결을 위해 네이티브(C/C++/어셈블리) 개발자가 JNI 네이티브 메서드를 직접 자바 클래스의 메서드와 연결할 수 있도록 RegisterNatives()라는 JNI 메서드를 제공하는데 이것을 사용하는 것이다. 자바가상머신이 자동으로 심볼을 검색해서 적절한 JNI네이티브 메서드를 연결시켜주는 방법에 비해서 프로그래머가 직접 연결을 하기 때문에 로딩 속도를 향상시킬 수 있는 것이다.
C. 장점 정리 (JNI 네이티브 함수를 직접 등록하는 방법의 장점)
i. 로딩속도 향상 (위에서 설명)
ii. JNI 네이티브 함수의 복잡한 네이밍 룰을 맞출 필요가 없다. 사용하는 자바클래스가 변경되면 JNI 메서드를 쉽게 변경할 수 있다. (아래의 사용법을 보면 이해가 되리라 본다.)
D. 동작방식
i. 자바코드에서 System.loadLibrary() 메서드를 호출하여 공유라이브러리를 로드한다.
ii. 자바가상머신(JVM)은 로드한 라이브러리 내의 함수심볼을 검색하여 JNI_OnLoad()라는 메서드가 구현되어 있는지 확인한다.
1. JNI_OnLoad() 메서드가 구현되어 있다면 그 메서드안에서 RegisterNative() 메서드를 이용하여 네이티브와 자바클래스간의 연결처리를 한다.
2. JNI_OnLoad()가 구현되어 있지 않다면, 자바가상머신은 자동으로 네이티브 메서드와 라이브러리 내의 JNI네이티브 메서드의 심볼을 비교하여 연결한다.
Cf. 참고
RegisterNative()메서드를 사용하면서 몇몇 메서드는 자동으로 연결하는 기능을 사용할 수도 있었다. (현재 네가 참여하고 있는 인프라웨어 이메일 코어 작업의 경우, 개선된 부분과 직접 연결하도록 했으나 미 개선 부분은 자동으로 여결하는 부분이 남아있으나 실행에는 아무런 문제가 없었다.)

덧글
4번 정도 코드 보며 읽으니까 이제야 이해가 되네요