NDK 및 JNI 에 대한 이해

hwiwon·2025년 8월 31일

Onboarding

목록 보기
2/3
post-thumbnail

NDK/JNI는 안드로이드 시스템/네이티브 성능 최적화 분야에서 필수로 쓰인다.
미러링처럼 초당 수십 장의 이미지를 압축하고, 전송해야 하는 작업은 Java나 Kotlin이 아닌 C나 C++ 같은 네이티브 언어를 사용한다.

NDK와 JNI는 코틀린/자바와 C/C++을 연결해주는 기술이다.

NDK (Native Development Kit)

안드로이드 앱에서 C/C++ 코드를 사용할 수 있게 해주는 개발 도구 모음.

C/C++ 코드를 안드로이드 앱에서 실행 가능한 형태로 컴파일, 빌드하는데 필요한 모든 것을 담고 있는 툴킷

주로 아래와 같은 경우에 사용된다

  • 성능 최적화
    높은 성능이 필요한 작업에 c/c++로 구현
    ex) 영상 처리, 게임, 복잡한 연산

  • 기존 라이브러리 재사용
    이미 c/c++로 만들어진 라이브러리 (ex. H.264 코덱 라이브러리)를 그대로 가져와 안드로이드 앱에 활용

  • 하드웨어 직접 제어
    특정 하드웨어 장치에 더 가깝게 접근해야 할 때

JNI (Java Native Interface)

자바/코틀린 코드와 c/c++ 네이티브 코드 간의 다리 역할을 하는 인터페이스

NDK가 개발 환경이라면,
JNI는 두 언어가 서로 호출하고 데이터를 주고받을 수 있도록 하는 규칙인 것.

kotlin에서 c++로 작성된 sum() 함수를 호출하려고 한다.

  1. 코틀린에서 sum(3,4)함수를 호출한다.
  2. JNI가 이 호출을 C++ 함수로 연결해준다.
  3. C++에서 int sum (int a, int b) 함수가 실행되어 결과를 계산한다.
  4. JNI가 그 결과를 다시 코틀린에게 전달한다.

빌드가 되는 Hello NDK 앱 만들기

안드로이드 환경 세팅

안드로이드 스튜디오에 NDK와 CMake 설치

새 프로젝트 생성 (Native C++)


native-lib.cpp


c++로 작성된 네이티브 코드

MainActivity.kt

익숙한 코틀린 코드에서의 네이티브 함수를 호출하는 파일

앱을 실행해 보면 native-lib.cpp의 stringFromJNI() 함수가 반환한 값을 MainActivity에서 받아서 화면에 띄우는 것을 볼 수 있다.


Main Activity 코드를 보면 ...

	/**
     * A native method that is implemented by the 'hellondk' native library,
     * which is packaged with this application.
     */
    external fun stringFromJNI(): String

external 키워드를 통해 네이티브 함수(C++ 라이브러리) 와 연결할 것임을 선언한다.

 companion object {
        // Used to load the 'hellondk' library on application startup.
        init {
            System.loadLibrary("hellondk")
        }
    }

라이브러리를 로딩하는 코드이다.
앱이 시작될 때 C++로 작성된 libhellondk.so 파일을 메모리에 올린다.

로드될 라이브러리 이름은 CMakeLists.txt 에서 지정된 이름을 사용한다.

// Example of a call to a native method
binding.sampleText.text = stringFromJNI()

이렇게 호출하여 사용한다.

더하기 함수 함 만들어보자.


먼저, MainActivity에서 호출할 함수 인터페이스 마냥 선언해서 만들어주고, 자동 생성 눌러주면


C++ 함수를 만들어준다.
저 긴긴 네이밍을 직접 쓰지 않아도 된다.

네이밍

Java_com_hwiwon_hellondk_MainActivity_addNumbers()
  • Java_ : 모든 JNI 함수 이름의 접두사
  • 패키지명: Java/Kotlin 파일의 패키지명 (com.hwiwon.hellondk 였던 것)
  • 클래스명: 함수가 속한 클래스명 (MainActivity)
  • 메서드명

인자

Java_com_hwiwon_hellondk_MainActivity_addNumbers(JNIEnv *env, jobject thiz, jint a, jint b)

마지막 2개의 a, b 파라미터는 실제 매개 변수라 그렇다 쳐도, *env, thiz는 뭘까?

JNIEvn *env

JNI 환경 포인터. C++ 함수가 자바 가상머신 JVM과 소통할 수 있는 통로이다.

이 포인터가 없으면, C++ 코드는 자바의 클래스나 객체에 접근할 수 없다.

  • Java/Kotlin 클래스 메소드 호출하기
  • Java/Kotlin 객체의 필드 값 읽거나 변경하기
  • Java/Kotlin 에서 문자열이나 배열을 생성하고 사용하기

jobject thiz

이 네이티브 함수를 호출한 Java/Kotlin 객체 자체를 가리키는 레퍼런스
C++에서 this와 비슷

  • 인스턴스 메소드의 경우
    thiz는 MainActivity의 특정 인스턴스를 가리킨다.
    해당 MainActivity가 가진 변수나 함수에 c++에서 접근할 수 있다.

  • 정적 메소드의 경우
    jobject 대신 jclass 타입이 온다.
    해당 함수를 호출한 클래스 자체를 가리킨다.

profile
안녕하십니까 공부 저장소에요

0개의 댓글