JNI_OnLoad和JNI_OnUnload

JNI_OnLoad和JNI_OnUnload 


一、引用

官方文档:https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html#library_version

JNI_OnLoad

jint JNI_OnLoad(JavaVM *vm, void *reserved);

    The VM calls  JNI_OnLoad  when the native library is loaded (for example, through  System.loadLibrary ).  JNI_OnLoad  must return the JNI version needed by the native library.

    In order to use any of the new JNI functions, a native library must export a JNI_OnLoad function that returns JNI_VERSION_1_2. If the native library does not export a JNI_OnLoad function, the VM assumes that the library only requires JNI version JNI_VERSION_1_1. If the VM does not recognize the version number returned by JNI_OnLoad, the native library cannot be loaded.

LINKAGE:

    Exported from native libraries that contain native method implementation.

SINCE:

    In order to use the JNI functions introduced in J2SE release 1.2, in addition to those that were available in JDK/JRE 1.1, a native library must export a JNI_OnLoad function that returns JNI_VERSION_1_2.

    In order to use the JNI functions introduced in J2SE release 1.4, in addition to those that were available in release 1.2, a native library must export a JNI_OnLoad function that returns JNI_VERSION_1_4.

    If the native library does not export a JNI_OnLoad function, the VM assumes that the library only requires JNI version JNI_VERSION_1_1. If the VM does not recognize the version number returned by JNI_OnLoad, the native library cannot be loaded.

JNI_OnUnload

    void JNI_OnUnload(JavaVM *vm, void *reserved);

    The VM calls  JNI_OnUnload  when the class loader containing the native library is garbage collected. This function can be used to perform cleanup operations. Because this function is called in an unknown context (such as from a finalizer), the programmer should be conservative on using Java VM services, and refrain from arbitrary Java call-backs.

    Note that JNI_OnLoad and JNI_OnUnload are two functions optionally supplied by JNI libraries, not exported from the VM.

二、JNI_OnLoad

    从官网中,可以了解到JNI_OnLoad()主要的几点:

  • 加载本地库的时被调用(例如,通过System.loadLibrary
  • 必须返回本地库所需的JNI版本
  • 用于保存JavaVM
    第一个参数是JavaVM,它是虚拟机在JNI层的代表,从JDK / JRE 1.2开始,不支持在单个进程中创建多个VM。那么在整个进程中javaVM只有一个,如果后面要使用,可以保存下来。
    JavaVM有什么作用呢?
    JNI接口指针(JNIEnv)仅在当前线程中有效。如果另一个线程需要访问Java VM,它必须先调用它 AttachCurrentThread()自己附加到VM并获得一个JNI接口指针(JNIEnv)。一旦连接到虚拟机,本地线程就像在本地方法内运行的普通Java线程一样工作。本地线程保持连接到VM直到它调用DetachCurrentThread() 分离自己。连接到VM的本地线程在退出之前必须调用DetachCurrentThread()以分离它自己。如果调用堆栈上有Java方法,则线程无法自行分离。

    简而言之调用JavaVM的AttachCurrentThread函数,就可得到这个线程的JNIEnv结构体。这样就可以在后台线程中回调Java函数了。另外,后台线程退出前,需要调用JavaVM的DetachCurrentThread函数来释放对应的资源。

  • 执行一些初始化操作
比如:获取java中的类,以便后面调用java中的函数
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
    log_android(ANDROID_LOG_INFO, "JNI load GetEnv failed");
    return -1;
 }
 const char *packet = "com/xxx/xxx/jniClass/Packet";

clsPacket = jniGlobalRef(env, jniFindClass(env, packet));

三、JNI_UNLoad

    当GC回收了加载这个库的ClassLoader时,该函数被调用,该函数可用于执行清理操作。由于这个函数是在未知的上下文中调用的,所以程序员在使用Java VM服务时应该保持谨慎,并且避免任意的Java回调

    JNIEnv *env;
    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK)
        log_android(ANDROID_LOG_INFO, "JNI load GetEnv failed");
    else {
        (*env)->DeleteGlobalRef(env, clsPacket);
        (*env)->DeleteGlobalRef(env, clsRR);
    }


你可能感兴趣的:(android)