JNI (JAVA Native Interface)

에이블·2022λ…„ 2μ›” 23일
2

Java

λͺ©λ‘ 보기
1/1

πŸ“‹ JNIλž€?

μžλ°” λ„€μ΄ν‹°λΈŒ μΈν„°νŽ˜μ΄μŠ€λŠ” μžλ°” 가상머신(JVM)μœ„μ—μ„œ μ‹€ν–‰λ˜κ³  μžˆλŠ” μžλ°”μ½”λ“œκ°€ λ„€μ΄ν‹°λΈŒ μ‘μš© ν”„λ‘œκ·Έλž¨(ν•˜λ“œμ›¨μ–΄μ™€ 운영 체제 ν”Œλž«νΌμ— μ’…μ†λœ ν”„λ‘œκ·Έλž¨λ“€) 그리고 C, C++ 그리고 μ–΄μ…ˆλΈ”λ¦¬ 같은

λ‹€λ₯Έ μ–Έμ–΄λ“€λ‘œ μž‘μ„±λœ λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ„ ν˜ΈμΆœν•˜κ±°λ‚˜ λ°˜λŒ€λ‘œ ν˜ΈμΆœλ˜λŠ” 것을 κ°€λŠ₯ν•˜κ²Œ ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° ν”„λ ˆμž„μ›Œν¬

πŸ“Œ μ‚¬μš©μ΄μœ 

  • 일뢀 ν•˜λ“œμ›¨μ–΄λ₯Ό μ²˜λ¦¬ν•΄μ•Ό ν•˜λŠ” ν•„μš”μ„±
  • 맀우 κΉŒλ‹€λ‘œμš΄ ν”„λ‘œμ„ΈμŠ€μ˜ μ„±λŠ₯ ν–₯상
  • Java둜 λ‹€μ‹œ μž‘μ„±ν•˜λŠ” λŒ€μ‹  μž¬μ‚¬μš©ν•˜λ €λŠ” κΈ°μ‘΄ 라이브러리

❗ 이λ₯Ό λ‹¬μ„±ν•˜κΈ° μœ„ν•΄ JDKλŠ” JVMμ—μ„œ μ‹€ν–‰λ˜λŠ” λ°”μ΄νŠΈμ½”λ“œμ™€ κΈ°λ³Έμ½”λ“œ 사이에 λΈŒλ¦¬μ§€λ₯Ό λ„μž…

πŸ“‹ μž‘λ™μ›λ¦¬

1. λ„€μ΄ν‹°λΈŒ λ©”μ†Œλ“œ

JavaλŠ” λ©”μ†Œλ“œ κ΅¬ν˜„μ΄ λ„€μ΄ν‹°λΈŒ μ½”λ“œμ—μ„œ 제곡될 κ²ƒμž„μ„ λ‚˜νƒ€λ‚΄λŠ” 데 μ‚¬μš©λ˜λŠ” λ„€μ΄ν‹°λΈŒ ν‚€μ›Œλ“œλ₯Ό 제곡
일반적으둜 λ„€μ΄ν‹°λΈŒ μ‹€ν–‰ ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€ λ•Œ 정적 λ˜λŠ” 곡유 라이브러리λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

  • 정적 라이브러리 - λͺ¨λ“  라이브러리 λ°”μ΄λ„ˆλ¦¬λŠ” μ—°κ²° ν”„λ‘œμ„ΈμŠ€ λ™μ•ˆ μ‹€ν–‰ 파일의 μΌλΆ€λ‘œ 포함. λ”°λΌμ„œ libsλŠ” 더 이상 ν•„μš”ν•˜μ§€ μ•Šμ§€λ§Œ μ‹€ν–‰ 파일의 크기가 증가

  • 곡유 라이브러리 - μ΅œμ’… μ‹€ν–‰ νŒŒμΌμ—λŠ” μ½”λ“œ μžμ²΄κ°€ μ•„λ‹Œ λΌμ΄λΈŒλŸ¬λ¦¬μ— λŒ€ν•œ 참쑰만 μžˆλ‹€. μ‹€ν–‰ νŒŒμΌμ„ μ‹€ν–‰ν•˜λŠ” ν™˜κ²½μ΄ ν”„λ‘œκ·Έλž¨μ—μ„œ μ‚¬μš©ν•˜λŠ” libs의 λͺ¨λ“  νŒŒμΌμ— μ•‘μ„ΈμŠ€ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.

곡유 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” λ°”μ΄νŠΈ μ½”λ“œμ™€ κ³ μœ ν•˜κ²Œ 컴파일된 μ½”λ“œλ₯Ό λ™μΌν•œ λ°”μ΄λ„ˆλ¦¬ νŒŒμΌμ— ν˜Όν•©ν•  수 μ—†κΈ° λ•Œλ¬Έμ— JNI에 λŒ€ν•΄ μ˜λ―Έκ°€ μžˆλ‹€.

λ”°λΌμ„œ 곡유 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” 클래슀의 일뢀가 μ•„λ‹Œ
.so .dll .dylib 파일 내에 λ„€μ΄ν‹°λΈŒ μ½”λ“œλ₯Ό λ³„λ„λ‘œ 보관

2. ν•„μš” κ΅¬μ„±μš”μ†Œ

❗ μžλ°” μ½”λ“œ
❗ λ„€μ΄ν‹°λΈŒ μ½”λ“œ
❗ JNI 헀더 파일
❗ C/C++ 컴파일러

java Code

  • λ„€μ΄ν‹°λΈŒ ν‚€μ›Œλ“œ - λ„€μ΄ν‹°λΈŒλ‘œ ν‘œμ‹œλœ λͺ¨λ“  λ©”μ†Œλ“œλŠ” λ„€μ΄ν‹°λΈŒ 곡유 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ κ΅¬ν˜„λ˜μ–΄μ•Ό ν•œλ‹€.

  • System.loadLibrary(String libname) - 곡유 라이브러리λ₯Ό 파일 μ‹œμŠ€ν…œμ—μ„œ λ©”λͺ¨λ¦¬λ‘œ λ‘œλ“œν•˜κ³  내보낸 ν•¨μˆ˜λ₯Ό Java μ½”λ“œμ—μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•˜λŠ” 정적 λ©”μ†Œλ“œ

C/C++ Code

  • JNIEXPORT - ν•¨μˆ˜λ₯Ό 곡유 λΌμ΄λΈŒλŸ¬λ¦¬μ— 내보내기 κΈ°λŠ₯으둜 ν‘œμ‹œν•˜μ—¬ ν•¨μˆ˜ ν…Œμ΄λΈ”μ— ν¬ν•¨λ˜λ―€λ‘œ JNIκ°€ 찿을 수 μžˆλ‹€.

  • JNICALL - JNIEXPORT와 κ²°ν•© ν•˜μ—¬ JNI ν”„λ ˆμž„μ›Œν¬μ—μ„œ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•œλ‹€.

  • JNIEnv - λ„€μ΄ν‹°λΈŒ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ Java μš”μ†Œμ— μ•‘μ„ΈμŠ€ν•  수 μžˆλŠ” λ©”μ†Œλ“œκ°€ ν¬ν•¨λœ ꡬ쑰

  • JavaVM - μ‹€ν–‰ 쀑인 JVM을 μ‘°μž‘ν•  수 μžˆλŠ” ꡬ쑰(λ˜λŠ” μƒˆ JVM μ‹œμž‘)에 Threadλ₯Ό run/interrupt... λ“±λ“±

πŸ’» "Hello World" (with JNI)

πŸ“Ÿ Step.1 JNI 선언이 ν¬ν•¨λœ Java Class

C둜 μž‘μ„±λœ μ½”λ“œμ—μ„œ μˆ˜ν–‰λ  λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•˜λŠ” 단계
예λ₯Ό λ“€μ–΄ "Hello World"λΌλŠ” λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•˜λŠ” λ„€μ΄ν‹°λΈŒ ν•¨μˆ˜κ°€ ν•„μš”ν•˜λ‹€λ©΄, λ‹€μŒκ³Ό 같이 μ½”λ”©ν•œλ‹€.

public native void getHello();
static{
	System.loadLibrary("JNI_Hello");
}

첫 Line은 λ©”μ†Œλ“œλ₯Ό μ„ μ–Έν•  λ•Œ 'native' ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.
μ΄λ ‡κ²Œ μ„ μ–Έν•˜λ©΄ getHello()κ°€ 호좜될 λ•Œ μžλ°”κ°€ μ•„λ‹Œ λ„€μ΄ν‹°λΈŒλ‘œ κ΅¬ν˜„λœ λ©”μ†Œλ“œλ₯Ό 찾게 λœλ‹€.

κ·Έ λ‹€μŒ Line은 λ„€μ΄ν‹°λΈŒλ‘œ μž‘μ„±λœ 라이브러리λ₯Ό μ§€μ •ν•˜λŠ” ꡬ문이닀.
μ—¬κΈ°μ„œλŠ” JNI_Hello.dll μ΄λΌλŠ” 라이브러리λ₯Ό λ‘œλ”©ν•˜κ³  μžˆλ‹€.

public class Hello{
	public native void getHello();
    
    static{
    	System.loadlibrary("JNI_Hello");
    }
    
    public Hello(){
    	getHello();
    }
    
    public static void main(String[] args){
    	new Hello();
    }
}

πŸ“Ÿ Step.2 javahλ₯Ό μ΄μš©ν•΄μ„œ C ν—€λ”νŒŒμΌ 생성

μƒμ„±λœ Hello.classλ₯Ό javah.exe ν”„λ‘œκ·Έλž¨μ„ μ΄μš©ν•΄μ„œ Hello.class νŒŒμΌλ‘œλΆ€ν„° C ν—€λ”νŒŒμΌμ„ 생성

# μœˆλ„μš° cmdλ₯Ό μ΄μš©ν•˜μ—¬ command μž…λ ₯

# 1. μƒμ„±ν•œ ν”„λ‘œμ νŠΈμ˜ bin ν΄λ”λ‘œ 이동
cd ~~~/Project_Name/bin

# 2. javah command μž…λ ₯
javah packagename.filename

진행이 μ™„λ£Œ 되면 λ‹€μŒκ³Ό 같은 ν—€λ”νŒŒμΌμ΄ μƒμ„±λœλ‹€.

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

#ifndef _Included_simple_Hello
#define _Included_simple_Hello
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     simple_Hello
 * Method:    getHello
 * Signature: ()V
 */

JNIEXPORT void JNICALL Java_simple_Hello_getHello
  (JNIEnv *, jobject);


#ifdef __cplusplus
}
#endif
#endif

이 ν—€λ”νŒŒμΌμ„ C둜 μ½”λ”©ν•  λ•Œ κ·Έλž˜λ„ μ‚¬μš©ν•˜κ³ 
쀑간에 μ„ μ–Έλœ

JNIEXPORT void JNICALL Java_simple_Hello_getHello(JNIEnv *, jobject);

λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ ν•  것이닀.

(이름을 보면 Java둜 μ‹œμž‘ν•˜κ³  νŒ¨ν‚€μ§€-클래슀-λ©”μ†Œλ“œ 이름 순으둜 μžλ™μƒμ„± λ˜μ—ˆλ‹€.)

πŸ“Ÿ Step.3 ν—€λ”νŒŒμΌμ— μ„ μ–Έλœ C λ©”μ†Œλ“œ 생성

본격적으둜 C μ†ŒμŠ€μ½”λ“œλ₯Ό μƒμ„±ν•˜κΈ° 이전에
μƒμ„±λœ ν”„λ‘œμ νŠΈμ˜ 속성을 λ³€κ²½ν•΄μ•Ό ν•œλ‹€.

ν”„λ‘œμ νŠΈ κΈ°λ³Έκ°’ - κ΅¬μ„±ν˜•μ‹μ„ 동적 라이브러리둜 λ°”κΎΈκ³ 
일반 - λŒ€μƒ ν™•μž₯λͺ…도 동적 라이브러리둜 λ³€κ²½ν•΄μ•Ό ν•œλ‹€.

λ”λΆˆμ–΄ μ™ΈλΆ€ 라이브러리 섀정을 톡해 μ—°κ²°ν•  jdkλ₯Ό μ„€μ •ν•΄μ•Ό ν•œλ‹€.

μžλ™μƒμ„±λœ ν—€λ”νŒŒμΌμ— μ„ μ–Έλ˜μ–΄ μžˆλŠ” ν•¨μˆ˜λ₯Ό C μ–Έμ–΄λ‘œ λ‹€μŒκ³Ό 같이 μ½”λ”©ν•œλ‹€.

JNIEXPORT void JNICALL Java_simple_Hello_getHello(JNIEnv *env, jobject obj){
        printf("Hello JNI\n");
        return;

}

πŸ“Ÿ Step.4 Test

Java ν”„λ‘œμ νŠΈλ‘œ λŒμ•„μ™€ Hello 클래슀λ₯Ό μ‹€ν–‰ν•΄λ³Έλ‹€.
Console 창에 "Hello JNI"κ°€ 보이면 성곡이닀.

μ‹€ν–‰ 절차λ₯Ό λ„μ‹ν™”ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€

ν˜„μž¬ ν¬μŠ€νŒ…μ€ JNI에 λŒ€ν•œ 맀우 κ°„λ‹¨ν•œ μ˜ˆμ œμ΄λ‹€.
λ‹€μŒ ν¬μŠ€νŒ…μ€ λ‹€μ–‘ν•œ 데이터 νƒ€μž…μ— λŒ€ν•œ JNI ν™œμš©μ— λŒ€ν•΄ μž‘μ„±μ˜ˆμ •

exit()

profile
꺾이지 μ•ŠλŠ” 마음

0개의 λŒ“κΈ€