🤖
JNI Tutorial
  • Introduction
  • 저자소개
  • Introduction
  • Hello JNI
  • 메서드 등록
  • int 데이터형 값 주고 받기
  • boolean 데이터형 값 주고 받기
  • double 데이터형 값 주고 받기
  • float 데이터형 값 주고 받기
  • long 데이터형 값 주고 받기
  • short 데이터형 값 주고 받기
  • char 데이터형 값 주고 받기
  • byte 데이터형 값 주고 받기
  • JNI에서 문자열 다루기 1/3
  • JNI에서 문자열 다루기 2/3
  • JNI에서 문자열 다루기 3/3
  • 레퍼런스 이해하기
  • 배열 다루기 1/4
  • 배열 다루기 2/4
  • 배열 다루기 3/4
  • 배열 다루기 4/4
  • 중간 요약
  • 자바 클래스 찾기 1/2
  • 자바 클래스 찾기 2/2
  • 정적 메서드 찾기
  • 정적필드 찾기
  • 자바 클래스 인스턴스 생성하기
  • 자바 클래스 인스턴스 메서드 찾기
  • 자바 클래스의 인스턴스 필드 찾기
  • 네이티브 쓰레드 실행하기
  • 작성 중...
Powered by GitBook
On this page

Was this helpful?

자바 클래스 인스턴스 메서드 찾기

자바 클래스의 인스턴스 메서드를 찾아 호출해 보는 예제를 작성해 보자. 자바 패키지에 존재하는 클래스의 인스턴스 메서드와 우리가 직접 만든 자바 클래스의 인스턴스 메서드를 호출해 볼 것이다.

인스턴스 메서드 호출은 네이티브 레이어에서 자바 레이어로 콜백하기 위해서 많이 쓰이기도 한다.

$ vi FindInstanceMethod.cpp
jstring toUpperString
(
    JNIEnv        *env,
    jobject        thiz,
    jstring        str
)
{
    //create String instance
    //find the string class
    jclass stringClass = env->FindClass("java/lang/String");
    if(stringClass == nullptr) {
        std::cout << "Failed to find the String class" << std::endl;
        return nullptr;
    }

    //find the contructor id
    jmethodID constructorID = env->GetMethodID(stringClass, "<init>", "(Ljava/lang/String;)V");
    if(constructorID == nullptr) {
        std::cout << "Failed to find the constructor of String class" << std::endl;
        return nullptr;
    }

    jstring stringObject = static_cast<jstring>( env->NewObject(stringClass, constructorID, str) );

    //find the toUpperCase Method
    jmethodID toUpperCaseID = env->GetMethodID(stringClass, "toUpperCase", "()Ljava/lang/String;");
    if(toUpperCaseID == nullptr) {
        std::cout << "Failed to find the toUpperCase method" << std::endl;
        return nullptr;
    }

    //call method
    return static_cast<jstring>(env->CallObjectMethod(stringObject, toUpperCaseID));
}

jstring toLowerString
(
    JNIEnv        *env,
    jobject        thiz,
    jstring        str
)
{
    //find the string class
    jclass stringClass = env->FindClass("java/lang/String");
    if(stringClass == nullptr) {
        std::cout << "Failed to find the String class" << std::endl;
        return nullptr;
    }

    //find the toLowerCase Method
    jmethodID toLowerCaseID = env->GetMethodID(stringClass, "toLowerCase", "()Ljava/lang/String;");
    if(toLowerCaseID == nullptr) {
        std::cout << "Failed to find the toLowerCase method" << std::endl;
        return nullptr;
    }

    //call method
    return static_cast<jstring>(env->CallObjectMethod(str, toLowerCaseID));
}


void doJobAndThenCallback
(
    JNIEnv        *env,
    jobject        thiz,
    jint            value
)
{
    //find the class of thiz object
    jclass thizClass = env->GetObjectClass(thiz);

    //find the onStart Method
    jmethodID onStartID = env->GetMethodID(thizClass, "onStart", "()V");
    if(onStartID == nullptr) {
        std::cout << "Failed to find the onStart method" << std::endl;
        return;
    }

    //call the onStart callback Method
    env->CallVoidMethod(thiz, onStartID);

    //do some jobs
    for(auto i=0; i<value; ++i) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    //find the onFinish Method
    jmethodID onFinishID = env->GetMethodID(thizClass, "onFinish", "()V");
    if(onFinishID == nullptr) {
        std::cout << "Failed to find the onFinish method" << std::endl;
        return ;
    }

    //call the onFinish callback Method
    env->CallVoidMethod(thiz, onFinishID);
}

JNIEXPORT jint JNICALL JNI_OnLoad
(
    JavaVM      *vm,
    void        *reserved
)
{
    JNIEnv      *env;
    if(vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) {
        return -1;
    }

    JNINativeMethod nm[3] ={

        {
            const_cast<char*>("toUpperString"),
            const_cast<char*>("(Ljava/lang/String;)Ljava/lang/String;"),
            reinterpret_cast<void*>(toUpperString)
        }
        ,
        {
            const_cast<char*>("toLowerString"),
            const_cast<char*>("(Ljava/lang/String;)Ljava/lang/String;"),
            reinterpret_cast<void*>(toLowerString)
        }
        ,
        {
            const_cast<char*>("doJobAndThenCallback"),
            const_cast<char*>("(I)V"),
            reinterpret_cast<void*>(doJobAndThenCallback)
        }

    };

    jclass cls = env->FindClass("Client");
    env->RegisterNatives(cls, nm, 3);
    return JNI_VERSION_1_6;
}

java.lang.String 클래스의 toUpperCase, toLowerCase 인스턴스 메서드를 찾아 호출하고 직접 만든 Client 클래스에서는 onStart, onFinish 인스턴스 메서드를 호출한다.

위 코드를 컴파일해서 라이브러리로 만든다.

$ g++ "-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/" -std=c++11 -c FindInstanceMethod.cpp
$ g++ -dynamiclib -o libfindinstancemethod.jnilib findinstancemethod.o

자바 코드에서 라이브러리를 사용해 보자.

$vi Client.java
public class Client {
    public native String toUpperString(String str);
    public native String toLowerString(String str);
    public native void doJobAndThenCallback(int value);


    public static void main(String[] args) {

        Client client = new Client();

        System.out.println("hello, world - " + client.toUpperString("hello, world"));
        System.out.println("HELLO, WORLD - " + client.toLowerString("HELLO, WORLD"));

        client.doJobAndThenCallback(5);
    }

    void onStart() {
        System.out.println("Starting the job...");
    }

    void onFinish() {
        System.out.println("Finished");
    }

    static {
        System.loadLibrary("findinstancemethod");
    }
}

컴파일하고 실행해 본다.

$ javac Client.java
$ java Client
hello, world - HELLO, WORLD
HELLO, WORLD - hello, world
Starting the job...
0 1 2 3 4
Finished
Previous자바 클래스 인스턴스 생성하기Next자바 클래스의 인스턴스 필드 찾기

Last updated 5 years ago

Was this helpful?