動的登録JNI

2193 ワード

従来のJNI登録は動的登録です
package wills.jniDemo

public class Utils{
    static{
      System.loadLibrary("native-lib");
    }

    public native String stringFromJNI();
}

//native-lib.cpp
JNIEXPORT 
jstring JNICALL Java_wills_jniDemo_Utils_stringFromJNI(JNIEnv *env, jobject instance) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

この静的登録には,nativeメソッドをJNIの形式で記述する必要がある.
次に、動的登録JNIについて説明します.例えば、このstringFromJNIをnativeメソッド名でsayHello()と定義したい場合について説明します.
package wills.jniDemo

public class Utils{
    static{
      System.loadLibrary("native-lib");
    }

    public native String stringFromJNI();
}

//native-lib.cpp
//      Java        ,     
jstring sayHello(JNIEnv *env, jobject obj) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

//      JNI       
static const char *jniClassName = "wills/jniDemo/Utils";
//  Java     native     
//"Java      ","    ","    native       "
static JNINativeMethod methods[] = {
        {"stringFromJNI", "()Ljava/lang/String;", (void *) jniSayHello},
};

static int registerNatives(JNIEnv *env) {
    jclass clazz = env->FindClass(jniClassName);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    jint methodSize = sizeof(methods) / sizeof(methods[0]);
    //RegisterNatives   ,"    ","     []","      "
    if (env->RegisterNatives(clazz, methods, methodSize) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

//      library         
JNIEXPORT jint  JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    if (!registerNatives(env)) {
        return JNI_ERR;
    }
    result = JNI_VERSION_1_6;
    return result;
}


これによりJNI仕様に適合したメソッド名を記述する必要がなくなり,nativeメソッドの探索速度を向上させることができるという.nativeメソッドが多い場合は、このように書くのも便利です.
方法についての署名はネット上の資料に基づいて自分で書くことができて、あるいは使うことができます
javap -s -p xxx.class

署名の取得に使用