본문 바로가기
JNI

[JNI] Java -jar로 실행시 C언어에서 findClass시 NoClassDefFoundError 발생 해결방법

by Apère 2023. 3. 16.
반응형

gradle bootRun으로 실행했을때 문제없었지만 jar로 실행시 NoClassDefFoundError가 발생했는데 차이는 클래스 로드방식때문입니다. 

Java VM은 JNI_OnLoad 함수를 호출하여, JNI 라이브러리를 초기화합니다. 이 때, 클래스를 전역변수로 저장하는 이유는, Java VM에서 클래스를 로딩하고, JNI 함수에서 사용하기 위함입니다.

Java 클래스는 Java VM에서 관리되며, Java 클래스는 클래스 로더(Class Loader)에 의해 로딩됩니다. JNI 함수에서 Java 클래스를 사용하기 위해서는, Java 클래스를 로딩하고, 해당 클래스의 메서드나 필드에 접근해야 합니다.

JNI_OnLoad 함수는 JNI 라이브러리를 초기화하는 시점에서 호출되므로, 이 함수에서 Java 클래스를 로딩하고, 전역변수로 저장하면, JNI 함수에서 해당 클래스를 사용할 수 있습니다. 이 때, 전역변수로 저장된 클래스는 JNI 라이브러리가 종료될 때까지 유지되므로, JNI 함수에서 여러번 사용될 수 있습니다.

따라서, JNI_OnLoad 함수에서 클래스를 전역변수로 저장하는 것은, JNI 함수에서 Java 클래스를 사용하기 위해 필요한 초기화 작업 중 하나입니다.

따라서 아래코드처럼 JNI_OnLoad시 jclass를 저장해놓고 사용하면 됩니다

static JavaVM* jvm;
static jclass testCls;

SWIGEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    jvm = vm;
    JNIEnv* env;
    jint res = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);

    if (res != JNI_OK) {
        return 0;
    }

    jclass testClsTemp = (*env)->FindClass(env, "Lcom/demo/test/handler/TestHandler;");
    if (testClsTemp == NULL) {
        (*jvm)->DetachCurrentThread(jvm);
        return 0;
    }
    testCls = (*env)->NewGlobalRef(env, testClsTemp);
    (*env)->DeleteLocalRef(env, testClsTemp);
    
    (*jvm)->DetachCurrentThread(jvm);

    return JNI_VERSION_1_8;
    
}
반응형

'JNI' 카테고리의 다른 글

[JNI] C에서 JAVA 코드를 호출하는 방법  (0) 2023.03.15
[JNI] JNI를 이용한 JAVA에서 C API 호출  (0) 2023.03.13

댓글