JNI development related to the previous also wrote several blogs, the Java native keyword definition of the method to register, are the use of Javah command to generate the corresponding Java _ package name _ class name _ method name, now can be generated by the compiler to help us, we go to fill in the corresponding logic code can be. This approach is called static registration. Today we’ll look at a new approach: dynamic registration

Instead of static registration where native methods are defined in a Java class and the compiler generates JNI methods, The basic idea of dynamic registration is to match the C/C++ and Java methods in the JNI_Onload() function with the RegisterNatives() method provided in JNI. The JNI_OnLoad () function will call back when we call System.loadLibrary, and the overall registration process is as follows:

  1. Define native methods in Java classes
  2. Write C/C++ code to implement the JNI_Onload() method
  3. Correspond Java methods to C/C++ methods through signature information
  4. Get JNIEnv from JavaVM. JNIEnv is mainly used to get Java classes and call some of the methods provided by JNI
  5. With the class name and corresponding method as parameters, call the JNI function RegisterNatives() to register the method

1. Java Native methods

public native String getStringFromC(a);

public native int getIntFromC(int index);
Copy the code

2, C/C++ method

jstring returnString(JNIEnv *env, jobject instance) {
    char *str = "I last come from c + +";
    return env->NewStringUTF(str);
}

jint returnInt(JNIEnv *env, jobject instance, jint index) {
    return index + 10;
}
Copy the code

3, JNINativeMethod

static JNINativeMethod gMethods[] = { {"getStringFromC", "()Ljava/lang/String;" , (void *) returnString}, {"getIntFromC", "(I)I", (void *) returnInt} };Copy the code
  • The native method name corresponding to the first parameter
  • The second parameter corresponds to the description of the native method
  • The third argument corresponds to the corresponding implementation in c++ code

This array maps Java layer functions to C/C++ layer code

4, JNI_Onload

int JNI_OnLoad(JavaVM *vm, void *re) {
    JNIEnv *env;
    if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) ! = JNI_OK) {return JNI_ERR;
    }

    jclass javaClass = env->FindClass("com/david/jnitestdemo/MainActivity");
    if (javaClass == NULL) {
        return JNI_ERR;
    }
    if (env->RegisterNatives(javaClass, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))"0) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}
Copy the code

env->RegisterNatives(javaClass, gMethods, sizeof(gMethods) / sizeof(gMethods[0])

The first is the corresponding jclass, the second is the array of JNINativeMethod, and the third is the number of functions

This completes the simple JNI dynamic registration Demo

Compare this to the previous static registration:

Static registration
extern "C" JNIEXPORT jstring JNICALL
Java_com_david_jnitestdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {}// Dynamic registration
jstring returnString(JNIEnv *env, jobject instance) {}Copy the code

In comparison, dynamic registration code will be some fresh, although more JNI_OnLoad and JNINativeMethod, but JNI_OnLoad can only write once, JNINativeMethod every time there is a new function to modify, so I feel dynamic registration code will be more comfortable, Also depends on personal habits, good enough here. ^ – ^