使用JNI可使Java代碼和其餘語言寫的代碼(如C/C++代碼)進行交互。linux
問:爲何要進行交互?程序員
|- 首先,Java語言提供的類庫沒法知足要求,且在數學運算,實時渲染的遊戲上,音視頻處理等方面上與C/C++相比效率稍低。函數
|- 而後,Java語言沒法直接操做硬件,C/C++代碼不只能操做硬件並且還能發揮硬件最佳性能。工具
|- 接着,使用Java調用本地的C/C++代碼所寫的庫,省去了重複開發的麻煩,而且能夠利用不少開源的庫提升程序效率。性能
C語言常見術語:spa
庫函數:操作系統
|- 爲了代碼重用,在C語言中提供了一些經常使用的、用於執行一些標準任務(如輸入/出)的函數,這些函數事先被編譯,並生成目標代碼,而後將生成的目標代碼打包成一個庫文件,以供再次使用。 庫文件中的函數被稱爲庫函數,庫文件被稱爲函數庫。視頻
|- 在Windows中C語言庫函數中的中間代碼都是以.obj爲後綴的,Linux中是以 .o爲後綴。接口
提示:單個目標代碼是沒法直接執行的,目標代碼在運行以前須要使用鏈接程序將目標代碼和其餘庫函數鏈接在一塊兒後生成可執行的文件。 Windows下.dll的文件 , linux下 .so .a的文件.遊戲
頭文件:
|- 頭文件中存放的是對某個庫中所定義的函數、宏、類型、全局變量等進行聲明,它相似於一份倉庫清單。若用戶程序中須要使用某個庫中的函數,則只須要將該庫所對應的頭文件include到程序中便可。
|- 頭文件中定義的是庫中全部函數的函數原型。而函數的具體實現則是在庫文件中。
|- 簡單的說:頭文件是給編譯器用的,庫文件是給鏈接器用的。
|- 在鏈接器鏈接程序時,會依據用戶程序中導入的頭文件,將對應的庫函數導入到程序中。頭文件以.h爲後綴名。
函數庫:
|- 動態庫:在編譯用戶程序時不會將用戶程序內使用的庫函數鏈接到用戶程序的目標代碼中,只有在運行時,且用戶程序執行到相關函數時纔會調用該函數庫裏的相應函數,所以動態函數庫所產生的可執行文件比較小。
|- 靜態庫:在編譯用戶程序時會將其內使用的庫函數鏈接到目標代碼中,程序運行時再也不須要靜態庫。使用靜態庫生成可執行文件比較大。
在Linux中:
|- 靜態庫命名通常爲:lib+庫名+.a 。
|- 如:libcxy.a 其中lib說明此文件是一個庫文件,cxy是庫的名稱,.a說明是靜態的。
|- 動態庫命名通常爲:lib+庫名+.so 。.so說明是動態的。
交叉編譯:
|- 將中間代碼鏈接成當前計算機可執行的二進制程序時,鏈接程序會根據當前計算機的CPU、操做系統的類型來轉換。
根據運行的設備的不一樣,能夠將cpu分爲:
|- arm結構 :主要在移動手持、嵌入式設備上。
|- x86結構 : 主要在臺式機、筆記本上使用。如Intel和AMD的CPU 。
若想在使用了基於x86結構CPU的操做系統中編譯出能夠在基於arm結構CPU的操做系統上運行的代碼,就必須使用交叉編譯。
交叉編譯:在一個平臺下編譯出在另外一個平臺中能夠執行的二進制代碼。Google提出的NDK就能夠完成交叉編譯的工做。
NDK全稱:Native Development Kit 。
|- NDK是一系列工具的集合,它有不少做用。
|- 首先,NDK能夠幫助開發者快速開發C(或C++)的動態庫。
|- 其次,NDK集成了交叉編譯器。使用NDK,咱們能夠將要求高性能的應用邏輯使用C開發,從而提升應用程序的執行效率。
NDK工具必須在Linux下運行,它能夠在linux環境下編譯出能夠在arm平臺下運行的二進制庫文件。
使用JNI技術,其實就是在Java程序中,調用C語言的函數庫中提供的函數,來完成一些Java語言沒法完成的任務。因爲Java語言和C語言結構徹底不相同,所以若想讓它們兩者交互,則須要制定一系列的規範。JNI就是這組規範,此時 Java只和JNI交互,而由JNI去和C語言交互。
JNI技術分爲兩部分:Java端和C語言端。且以Java端爲主導。
|- 首先,Java程序員在Java端定義一些native方法,並將這些方法以C語言頭文件的方式提供給C程序員。
|- 而後,C程序員使用C語言,來實現Java程序員提供的頭文件中定義的函數。
|- 接着,C程序員將函數打包成一個庫文件,並將庫文件交給Java程序員。
|- 最後,Java程序員在Java程序中導入庫文件,而後調用native方法。
在Java程序執行的時候,若在某個類中調用了native方法,則虛擬機會經過JNI來轉調用庫文件中的C語言代碼。提示:C代碼最終是在Linux進程中執行的,而不是在虛擬機中。