반응형
C에서 JAVA 코드를 호출하기위해서는 jvm이 필요합니다.
java에서 dll 이나 so를 로드하게 되면 c의 JNI_Onload 코드가 호출되게 된다. 이때 우선 jvm을 전역변수로 저장해둡니다.
static JavaVM* jvm;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
jvm = vm;
return JNI_VERSION_1_8;
}
그런다음 자바에 c언어에서 호출될 클래스와 메서드를 만듭니다.
@Slf4j
public class TestHandler {
public TestHandler() {
}
public void testHandler(String str) {
log.info(str);
}
}
이제 저장해둔 jvm을 이용하여 위의 코드를 c언어코드에서 실행해봅시다.
void
testHandler()
{
JNIEnv* env;
jint res = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);
if (res != JNI_OK) {
return;
}
jclass cls = (*env)->FindClass(env, "Lcom/demo/test/handler/TestHandler;");
if (cls == NULL) {
(*jvm)->DetachCurrentThread(jvm);
return;
}
jmethodID constructor = (*env)->GetMethodID(env, cls, "<init>", "()V");
if (constructor == NULL) {
(*jvm)->DetachCurrentThread(jvm);
return;
}
jobject obj = (*env)->NewObject(env, cls, constructor);
if (obj == NULL) {
(*jvm)->DetachCurrentThread(jvm);
return;
}
jmethodID mid = (*env)->GetMethodID(env, cls, "testHandler", "(Ljava/lang/String;)V");
if (mid == NULL) {
(*jvm)->DetachCurrentThread(jvm);
return;
}
jstring str = (*env)->NewStringUTF(env, (const char *)"test");
(*env)->CallVoidMethod(env, obj, mid, str);
(*jvm)->DetachCurrentThread(jvm);
}
int main(int argc, char** argv) {
testHandler();
}
jvm을 이용하여 JNIEnv를 만들고 호출할 메서드가 있는 자바 클래스를 찾습니다. 패키지명까지 정확하게 입력해야 합니다. 그런다음 해당 클래스의 생성자 함수를 호출합니다. 만약 스프링환경을 사용한다면 생성자 함수에 DI를 처리할 수 있습니다. 그런다음 testHandler 메서드를 찾습니다. 메서드이름, 파라미터와 리턴타입도 정확하게 입력해야 합니다
마지막으로 리턴타입에 맞게 CallMethod를 해주면 자바 어플리케이션에서 로그를 확인하실수 있습니다. 참고로 NewStringUFT로 생성된 문자열은 jvm에서 관리하므로 c언어에서 별도의 클리어는 해주지 않아도 됩니다.
반응형
'JNI' 카테고리의 다른 글
[JNI] Java -jar로 실행시 C언어에서 findClass시 NoClassDefFoundError 발생 해결방법 (0) | 2023.03.16 |
---|---|
[JNI] JNI를 이용한 JAVA에서 C API 호출 (0) | 2023.03.13 |
댓글