자바 클래스 인스턴스 메서드 찾기
자바 클래스의 인스턴스 메서드를 찾아 호출해 보는 예제를 작성해 보자. 자바 패키지에 존재하는 클래스의 인스턴스 메서드와 우리가 직접 만든 자바 클래스의 인스턴스 메서드를 호출해 볼 것이다.
인스턴스 메서드 호출은 네이티브 레이어에서 자바 레이어로 콜백하기 위해서 많이 쓰이기도 한다.
$ 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
Last updated
Was this helpful?