超人高校免费观看:Jserv's blog: JNI_OnLoad 的非預期現象

来源:百度文库 编辑:九乡新闻网 时间:2024/04/20 03:47:29

JNI_OnLoad 的非預期現象

Alan Burlison 在 blog [JNI_OnUnload(): mostly useless] 提到 JNI_Unload 這個 JNI call 搭配 JNIInvokeInterface 的 AttachCurrentThread call 造成非預期的現象。在 kaffe/include/jni.h 中,相關的定義如下:
    /* These functions might be defined in libraries
    which we load; the JNI implementation calls
    them at the appropriate times. */
    extern JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM *, void *);
    extern JNIEXPORT void JNICALL JNI_OnUnload (JavaVM *, void *);

    /*
    * Invocation API.
    */
    struct JNIInvokeInterface
    {
    void *reserved0;
    void *reserved1;
    void *reserved2;

    jint (JNICALL *DestroyJavaVM) (JavaVM *);
    jint (JNICALL *AttachCurrentThread) (JavaVM *, void **, void *);
    jint (JNICALL *DetachCurrentThread) (JavaVM *);
    jint (JNICALL *GetEnv) (JavaVM *, void **, jint);
    jint (JNICALL *AttachCurrentThreadAsDaemon) (JavaVM *, void **, void *);
    };
Alan Burlison 指出問題的癥結:
    what was puzzling me was that although JNI_OnLoad() was being called OK, JNI_OnUnload() was never being called, and because the thread was attached to the JVM via a call to AttachCurrentThread(), the JVM would never exit as it still had an active thread. A simple workaround was to attach the thread to the JVM as a daemon thread using AttachCurrentThreadAsDaemon as daemon threads don't keep the JVM alive, but that still meant the DLL wasn't being cleaned up properly.
稍後他試著解決問題,過去可用 java.lang.System.runFinalizersOnExit() method,不過這已經 deprecated,他最後使用的解法如下:
    In light of this it appears that although JNI_OnLoad() is useful, JNI_OnUnload() is less than useful. There is a workaround, which is to register a native exit callback using Runtime.addShutdownHook() and do the cleanup that way, but it's kind of broken that JNI_OnUnload() doesn't actually do what it is supposed to, and even more odd that the JNI documentation is completely silent as to why it doesn't actually work.
在 GNU Classpath (Kaffe 算是其「超集」) 中,package gnu.xml.libxmlj.util用到這個技巧,可參閱 gnu/xml/libxmlj/util/XMLJ.java 在 initialization 的部份程式碼,其 JNInative impl 位於 native/jni/xmlj/xmlj_util.c。