Java 之 native 關鍵字與 registerNatives 方法


一、native 關鍵字

   native 的本意是原生的,本地的。

   native 是一個修飾符,只可以用來修飾方法。

   native 修飾的方法,看不見方法體;

 

   native 修飾的方法,不是用 Java 語言實現的,而是調用了底層 C/C++ 的代碼,這些代碼為 .dll 文件,讓 Java來執行。

 

   native 關鍵字是 JNI(Java Native Interface)的重要體現。什么是 JNI ,JNI 是Java調用其他語言(c,c++) 的一種機制。native 關鍵字修飾的是方法,起聲明作用,告訴 JVM 老哥自己去調用這個方法。這個方法的實現在別的語言那里已經實現,我們是看不到源碼的。

  使用 native 關鍵字說明這個方法是原生函數,也就是這個方法是用 C/C++等非Java 語言實現的,並且被編譯成了 DLL,由 java 去調用。

  (1)為什么要用 native 方法?

    Java 使用起來非常方便,然而有些層次的任務用 Java 實現起來不容易,或者我們對程序的效率很在意時,問題就來了。例如:有時 java 應用需要與 java 外面的環境交互。這是本地方法存在的主要原因,你可以想想 java 需要與一些底層系
統如操作系統或某些硬件交換信息時的情況。本地方法正是這樣一種交流機制:它為我們提供了一個非常簡潔的接口,而且我們無需去了解 java 應用之外的繁瑣的細節。

  (2)native 聲明的方法,對於調用者,可以當做和其他 Java 方法一樣使用

    一個 native method 方法可以返回任何 java 類型,包括非基本類型,而且同樣可以進行異常控制。
    native method 的存在並不會對其他類調用這些本地方法產生任何影響,實際上調用這些方法的其他類甚至不知道它所調用的是一個本地方法。 JVM 將控制調用
本地方法的所有細節。
    如果一個含有本地方法的類被繼承,子類會繼承這個本地方法並且可以用 java語言重寫這個方法(如果需要的話)。

二、本地方法

   Java有兩種方法:Java方法和本地方法。Java方法是由Java語言編寫,編譯成字節碼,存儲在class文件中。本地方法是由其他語言(比如C,C++,或者匯編)編寫的,編譯成和處理器相關的機器代碼。本地方法保存在動態連接庫中,格式是各個平台專有的。Java方法是平台無關的,不過本地方法卻不是。運行中的Java程序調用本地方法時,虛擬機裝載包含這個本地方法的動態庫,並調用這個方法。本地方法是聯系Java程序和底層主機操作系統的連接方法。

三、registerNatives 本地方法

  1、registerNatives本地方法的作用是什么?

    registerNatives 方法

1 private static native void registerNatives();
2 static {
3     registerNatives();
4 }

    從上面的代碼中看到Object類定義了一個靜態初始化塊,我們知道當創建Java對象時,系統總是先調用靜態初始化塊

    在上面的靜態初始化塊中調用了registerNatives()方法,並且使用了private來修飾,表面這個方法是私有的並不被外部調用。

    本地方法的實現是由其他語言編寫並保存在動態連接庫中,因而在java類中不需要方法實現。registerNatives本質上就是一個本地方法,但這又是一個有別於一般本地方法的本地方法,從方法名我們可以猜測該方法應該是用來注冊本地方法的。事實上,上述代碼的功能就是先定義了registerNatives()方法,然后當該類被加載的時候,調用該方法完成對該類中本地方法的注冊。

    registerNatives函數前面有native關鍵字修飾,Java中,用native關鍵字修飾的函數表明該方法的實現並不是在Java中去完成,而是由C/C++去完成,並被編譯成了.dll,由Java去調用。方法的具體實現體在dll文件中,對於不同平台,其具體實現應該有所不同。用native修飾,即表示操作系統,需要提供此方法,Java本身需要使用。具體到registerNatives()方法本身,其主要作用是將C/C++中的方法映射到Java中的native方法,實現方法命名的解耦。

  2、到底注冊了哪些方法?

    在Object類中,除了有registerNatives這個本地方法之外,還有hashCode()、clone()等本地方法,而在Class類中有forName0()這樣的本地方法等等。也就是說,凡是包含registerNatives()本地方法的類,同時也包含了其他本地方法。所以,顯然,當包含registerNatives()方法的類被加載的時候,注冊的方法就是該類所包含的除了registerNatives()方法以外的所有本地方法。

  3、為什么要注冊?

      一個Java程序要想調用一個本地方法,需要執行兩個步驟:

    (1)通過System.loadLibrary()將包含本地方法實現的動態文件加載進內存;

    (2)當Java程序需要調用本地方法時,虛擬機在加載的動態文件中定位並鏈接該本地方法,從而得以執行本地方法。

    registerNatives()方法的作用就是取代第二步,讓程序主動將本地方法鏈接到調用方,當Java程序需要調用本地方法時就可以直接調用,而不需要虛擬機再去定位並鏈接。

  4、registerNatives() 本地方法的好處

  • 通過registerNatives方法在類被加載的時候就主動將本地方法鏈接到調用方,比當方法被使用時再由虛擬機來定位和鏈接更方便有效;
  • 如果本地方法在程序運行中更新了,可以通過調用registerNative方法進行更新;
  • Java程序需要調用一個本地應用提供的方法時,因為虛擬機只會檢索本地動態庫,因而虛擬機是無法定位到本地方法實現的,這個時候就只能使用registerNatives()方法進行主動鏈接。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM