native 方法的鏈接

之前舉了一個簡單的JNI demo。

我們回顧一下:

package diveinjvm;

public class Foo {
//        public static native void foo();
//        public native void bar(int i, long j);
        public native void bar(String s, Object o);

        int i = 0xDEADBEEF;

        public static void main(String[] args) {
            try {
                System.loadLibrary("foo");
            } catch (UnsatisfiedLinkError e) {
                e.printStackTrace();
                System.exit(1);
            }
            new Foo().bar("", "");
        }
    }

這裏就產生一個問題。Foo.java中的bar方法怎麼就知道調用到那個c方法呢?

我們通過javac -h Foo.java命令生成了一個.h文件,我們注意下這個文件裏的方法名:Java_diveinjvm_Foo_bar

這裏可以看出,方法名以Java_開頭+包名_+類名_+方法名。

這種情況屬於 Java 虛擬機自動查找符合默認命名規範的 C 函數。

還要一個情況

我們看下java.lang.Object這個類有很多native方法比如:

public native int hashCode();

並且Object類開頭有一段代碼

private static native void registerNatives();
    static {
        registerNatives();
    }

registerNatives方法應該也對應一個c方法。

查看openJdk的源代碼,openjdk\openjdk8\openjdk\jdk\src\share\native\java\lang\Object.c

static JNINativeMethod methods[] = {
    {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}

這裏對hashCode進行了註冊。這樣調用Object類中的hashCode就能調用到openjdk\openjdk8\openjdk\jdk\src\share\native\java\lang\Object.c中的JVM_IHashCode方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章