반응형
프로젝트를 진행하면서 JNI에 대해 알게 되었었다. Java에서 C함수를 호출하거나 C에서 Java의 메소드를 호출할 때 사용하는 것인데, 안드로이드 공부를 하다가 조금 더 파고들게 되었다.
* 안드로이드는 자바로 프로그래밍을 하는데 왜 JNI에 대해 알아야 할까?
우선 안드로이드 플랫폼은 순수하게 Java로만 구성되어진 것이 아닌 Java 레이어와 C/C++레이어가 서로 상호 작용하면서 동작한다. 이 두 레이어가 유기적으로 동작하게 만들려면 JNI에 대해 알아야 한다.
그리고 일반적으로 Java는 C/C++에 비해 느리다. 성능이 중요할 경우 C/C++로 작성하고 이를 JNI를 통해 Java에서 호출할 수 있다.
* NDK(Native Development Kit)
안드로이드 애플리케이션에서 사용할 네이티브 라이브러리를 작성하기 위한 도구 모음.
실제로 모듈을 구현하기 위해서는 JNI에 대한 지식 필요
* JNI의 개발 순서
1. Java 코드 작성
2. Java 코드 컴파일
3. C 헤더 파일 생성
4. C 코드 작성
5. C 공유 라이브러리 생성
6. Java 프로그램 실행
1. Java 코드 작성
public class AtinJNI {
// 네이티브 메소드 선언
[표 1] 플랫폼별 System.loadLibrary() 메소드가 로딩하는 C라이브러리 형식
2. Java 코드 컴파일
javac를 통해서 .java파일을 .class로 컴파일한다.
위와 같은 명령을 실행할 경우 아무 에러가 나지 않는다면 .class로 컴파일 된 것이다.
3. C 헤더 파일 생성
이제 Java 소스를 만들었으니 C 소스를 짜야 한다. 그런데 중요한 점은 어떻게 Java에서 호출되는 C 소스를 짤 것인가이다. 이것을 위해 javah라는 툴이 있다. 이 툴을 사용하면 .class파일을 파싱해서 만들어야 할 C 함수의 헤더를 만들어준다.
javah <native로 선언된 메소드를 포함한 자바 클래스명>
- <JDK_HOME>\bin에 포함.
- Java 네이티브 메소드와 연결될 수 있는 C함수의 원형 생성
위와 같은 명령어를 실행하면 AtinJNI.h라는 헤더 파일이 생성됀다.
내용은 아래와 같다.
[Source 2] AtinJNI.h
4. C 코드 작성
위에서 생성한 AtinJNI.h의 헤더를 기준으로 C 소스를 작성하면 됀다.
[Source 3] atinjni.c
5. C 공유 라이브러리 생성
중요한건 Window는 dll, Linux는 so파일을 만들어야 한다. 책에서는 C 소스를 작성 후 cl명령을 통해 dll을 만들었다.
cl 명령은 Visual Studio 2008 명령 프롬프트에서 실행해야 하며 VC 2008 Express Editions(http://www.microsoft.com/express/download/)가 설치되어 있어야 한다.
cl -I"<JDK_HOME>\include" -I"<JDK_HOME>\include\win32" -LD atinjni.c -Featinjni.dll
cl : vc++ 컴파일 명령어
-I<dir> : 헤더 파일을 검색할 디렉토리 경로 <dir> 추가
-LD : DLL 생성
-FE<파일명> : 컴파일 결과 파일 이름 지정
나는 VC에서 직접하고 싶어서 [1]과 같이 dll을 만들었다.
그런데 다음과 같은 문제에 직면했다.
Can't load IA 32-bit .dll on a AMD 64-bit platform
그래. 나는 64비트용 윈도우 7 운영체제였다. 32비트 dll이 문제가 되는 것이었다. 구글링해보니 32비트용으로 Java를 다시 까니 실행 명령어에 옵션을 주는 몇 방법들이 있었는데 마음에 들지 않았다. dll을 64비트용으로 하면 될 것 같았다. 그래서 [2]와 같은 방법으로 dll을 64비트용으로 만들어주었고 문제를 해결했다.
6. Java 프로그램 실행
이클립스라면 그냥 실행하면 되고 콘솔에서라면 "java AtinJNI"로 실행하면 결과를 볼 수 있다.
Reference
[1] VC에서 DLL 만드는 방법 (http://sol9501.blog.me/70102942944)
[2] 64비트용 컴파일 (http://blog.naver.com/PostView.nhn?blogId=honnak&logNo=70085595801&viewDate=¤tPage=1&listtype=0)
[3] 인사이드 안드로이드(Inside the Android Framework, 위키북스)
* 안드로이드는 자바로 프로그래밍을 하는데 왜 JNI에 대해 알아야 할까?
우선 안드로이드 플랫폼은 순수하게 Java로만 구성되어진 것이 아닌 Java 레이어와 C/C++레이어가 서로 상호 작용하면서 동작한다. 이 두 레이어가 유기적으로 동작하게 만들려면 JNI에 대해 알아야 한다.
그리고 일반적으로 Java는 C/C++에 비해 느리다. 성능이 중요할 경우 C/C++로 작성하고 이를 JNI를 통해 Java에서 호출할 수 있다.
* NDK(Native Development Kit)
안드로이드 애플리케이션에서 사용할 네이티브 라이브러리를 작성하기 위한 도구 모음.
실제로 모듈을 구현하기 위해서는 JNI에 대한 지식 필요
* JNI의 개발 순서
1. Java 코드 작성
2. Java 코드 컴파일
3. C 헤더 파일 생성
4. C 코드 작성
5. C 공유 라이브러리 생성
6. Java 프로그램 실행
1. Java 코드 작성
// 네이티브 메소드 선언
native void printAtin();
native void printString(String str);
// 라이브러리 로딩
static {System.loadLibrary("atinjni");}
public static void main(String args[]){
AtinJNI myJNI = new AtinJNI();
// 네이티브 메소드 호출
myJNI.printAtin();
myJNI.printString("Hello Atin");
}
}
[Source 1] AtinJNI.java[표 1] 플랫폼별 System.loadLibrary() 메소드가 로딩하는 C라이브러리 형식
호스트 플랫폼 | 실제 로드되는 C 라이브러리 |
Window | libname.dll |
Linux | libname.so |
2. Java 코드 컴파일
javac를 통해서 .java파일을 .class로 컴파일한다.
javac AtinJNI.java |
위와 같은 명령을 실행할 경우 아무 에러가 나지 않는다면 .class로 컴파일 된 것이다.
3. C 헤더 파일 생성
이제 Java 소스를 만들었으니 C 소스를 짜야 한다. 그런데 중요한 점은 어떻게 Java에서 호출되는 C 소스를 짤 것인가이다. 이것을 위해 javah라는 툴이 있다. 이 툴을 사용하면 .class파일을 파싱해서 만들어야 할 C 함수의 헤더를 만들어준다.
javah <native로 선언된 메소드를 포함한 자바 클래스명>
- <JDK_HOME>\bin에 포함.
- Java 네이티브 메소드와 연결될 수 있는 C함수의 원형 생성
javah AtinJNI |
내용은 아래와 같다.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class AtinJNI */
#ifndef _Included_AtinJNI
#define _Included_AtinJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: AtinJNI
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_AtinJNI_printHello
(JNIEnv *, jobject);
/*
* Class: AtinJNI
* Method: printString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_AtinJNI_printString
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
4. C 코드 작성
위에서 생성한 AtinJNI.h의 헤더를 기준으로 C 소스를 작성하면 됀다.
#include "HelloJNI.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_AtinJNI_printAtin
(JNIEnv *env, jobject obj)
{
printf("Hello Atin \n");
return;
}
JNIEXPORT void JNICALL Java_AtinJNI_printString
(JNIEnv *env, jobject obj, jstring string)
{
const char *str = (*env)->GetStringUTFChars(env, string, 0);
printf("%s! \n", str);
return;
}
5. C 공유 라이브러리 생성
중요한건 Window는 dll, Linux는 so파일을 만들어야 한다. 책에서는 C 소스를 작성 후 cl명령을 통해 dll을 만들었다.
cl 명령은 Visual Studio 2008 명령 프롬프트에서 실행해야 하며 VC 2008 Express Editions(http://www.microsoft.com/express/download/)가 설치되어 있어야 한다.
cl -I"<JDK_HOME>\include" -I"<JDK_HOME>\include\win32" -LD atinjni.c -Featinjni.dll
cl : vc++ 컴파일 명령어
-I<dir> : 헤더 파일을 검색할 디렉토리 경로 <dir> 추가
-LD : DLL 생성
-FE<파일명> : 컴파일 결과 파일 이름 지정
나는 VC에서 직접하고 싶어서 [1]과 같이 dll을 만들었다.
그런데 다음과 같은 문제에 직면했다.
Can't load IA 32-bit .dll on a AMD 64-bit platform
그래. 나는 64비트용 윈도우 7 운영체제였다. 32비트 dll이 문제가 되는 것이었다. 구글링해보니 32비트용으로 Java를 다시 까니 실행 명령어에 옵션을 주는 몇 방법들이 있었는데 마음에 들지 않았다. dll을 64비트용으로 하면 될 것 같았다. 그래서 [2]와 같은 방법으로 dll을 64비트용으로 만들어주었고 문제를 해결했다.
6. Java 프로그램 실행
이클립스라면 그냥 실행하면 되고 콘솔에서라면 "java AtinJNI"로 실행하면 결과를 볼 수 있다.
Reference
[1] VC에서 DLL 만드는 방법 (http://sol9501.blog.me/70102942944)
[2] 64비트용 컴파일 (http://blog.naver.com/PostView.nhn?blogId=honnak&logNo=70085595801&viewDate=¤tPage=1&listtype=0)
[3] 인사이드 안드로이드(Inside the Android Framework, 위키북스)
반응형
'Devlopment > Java' 카테고리의 다른 글
JavaHL (JNI) Not Available (0) | 2011.06.10 |
---|---|
Builder Pattern (0) | 2011.06.09 |
달팽이 & 피보나치 수열 구현 (0) | 2011.06.01 |
JNI(Java Native Interface) - 객체 (0) | 2011.06.01 |
두 개의 스택을 이용한 큐 구현 (0) | 2011.05.31 |
System.out.println의 재정의 (0) | 2011.05.13 |
[Linux, Window] JAVA로 로컬 IP 주소 얻어오는 방법 (0) | 2011.05.09 |
자바 enum에서 내부 String (0) | 2011.04.08 |
자바 Exception의 printStackTrace 구현. (0) | 2011.04.07 |
자바 개발시 오버라이드 @Override를 꼭 사용하자 (0) | 2010.08.27 |