JNIjava
開始本篇的內容以前,首先要講一下JNI。Java很好,使用的人不少、應用極 廣,可是Java不是完美的。Java的不足體如今運行速度要比傳統的C++慢上許多以外,還有Java沒法直接訪問到操做系統底層如硬件系統,爲此 Java提供了JNI來實現對於底層的訪問。JNI,Java Native Interface,它是Java的SDK一部分,JNI容許Java代碼使用以其餘語言編寫的代碼和代碼庫,本地程序中的函數也能夠調用Java層的函 數,即JNI實現了Java和本地代碼間的雙向交互。函數
Nativespa
JDK開放給用戶的源碼中隨處可見Native方法,被Native關鍵字聲明的方法說明該方法不是以Java語言實現的,而是以本地語言實現的,Java能夠直接拿來用。這裏有一個概念,就是本地語言,本地語言這四個字,我的理解應該就是能夠和操做系統直接交互的語言。操作系統
經過JNI調用C++寫的代碼命令行
下面演示一下如何寫一段簡單的C++代碼,在Java中用一個Native方法去調用的步驟。C++代碼使用到的IDE是Microsoft Visual Studio 2010,這是一款市面上開發C++代碼最經常使用的IDE,功能強大。OK,接下來一步一步演示一下:3d
一、寫一段Java代碼。因爲咱們在Windows環境下,因此用的是一 個.dll文件,若是在Linux環境下的話,用的是一個.so文件。最後C++代碼寫完以後要生成一個.dll/.so文件,生成的文件可使用 static靜態加載的方法加載進來,也能夠經過配置環境變量的方式,這裏選擇前者。code
1 public class TestMain 2 { 3 static 4 { 5 System.load("D:" + File.separator + "Hello.dll"); 6 } 7 8 public native static void Hello(); 9 10 public static void main(String[] args) 11 { 12 Hello(); 13 } 14 }
二、cmd進入命令行程序中,進入剛纔寫的那個類的CLASSPATH下,CLASSPATH就是.class文件所在的根路徑。運行「JNI -jni com.xrq.test1.TestMain」 ,表示爲指定的類下的Native方法生成.h文件。.h文件是C/C++使用的頭文件,用於將聲明和實現分離,不熟悉C/C++的同窗也不用深究blog
三、進入本身的CLASSPATH底下查看一下有沒有多一個.h文件,我本身這邊的是開發
這個命名是javah這個命令的實現幫咱們命名的,只要多了這個文件就能夠了cmd
四、打開VS2010,文件-->新建-->項目,命名爲「Hello」,和咱們靜態塊中load進去的名字要一致
注意選擇DLL
五、剛纔經過javah生成的.h文件複製到Hello目錄下
六、把這個.h添加到項目中,右鍵頭文件-->添加-->現有項,選擇Hello目錄下的「com_xrq_test1_TestMain.h」添加進去就行了
七、右鍵 源文件-->添加-->新建項,選擇.cpp文件,隨便命名,我叫作source.cpp。實現很簡單,就打印一下「Hello」這個字符 串。cout是C++的控制檯輸出語句,至關於Java的System.out.print(),endl是換行的意思,因此這整句至關於Java的 System.out.println("Hello");
八、修改「com_xrq_test1_TestMain.h」頭文件中的#include <jni.h>爲#include "jni.h"
九、把%JAVA_HOME%/include目錄下的「jni.h」和%JAVA_HOME%/include/win32目錄下的「jni_md.h」兩 個文件複製到Hello目錄下,用剛纔添加「com_xrq_test1_TestMain.h」同樣的方式添加這兩個.h文件到頭文件目錄中,這樣目錄 下Hello目錄下應該多出了兩個文件,VS2010工程目錄下應該有3個.h文件。JAVA_HOME就是JDK安裝目錄,不知道的cmd進入命令行,echo %JAVA_HOME%就能夠查看了。這一步很重要,沒有這一步,C++程序是沒法運行的
十、右鍵項目-->生成,就能夠生成.dll文件了
十一、剛纔生成的.dll文件是32系統下的,32系統的用戶能夠直接使用這 個.dll文件了,只要複製到靜態代碼塊指定的目錄下就行了。換句話說,64位系統的用戶是不能使用這個.dll文件的。若是要生成64位計算機可使用 的.dll文件,還要額外再爲64位計算機成生一個.dll文件
下拉菜單裏面沒有x64的點擊下拉菜單-->配置管理器配置一下,本身摸索一下就行了,VS2010有自帶x64的
十二、生成64位的.dll,複製到D盤下便可,也就是靜態代碼塊裏面指定的Hello.dll的路徑
1三、運行一下第一步裏面寫的Java程序,C++打印的「Hello」就出來了,至此,Java經過JNI調用C++編寫的代碼的功能完成。
有什麼心得?
本身完成了這麼一個過程,確定是很有成就感的,成就感事後,咱們能夠從這13個步驟中感悟到什麼?至少我的有如下心得:
一、1個類中有不少Native方法-->這個類中的全部Native方法生成到1個.h文件中-->本地代碼生成一個.dll/.so文件和一個類的Native方法實現相對應
二、爲何有Native方法的類中必有這麼一段代碼
1 private static native void (); 2 static { 3 registerNatives(); 4 }
如今想來,估計和咱們的靜態代碼塊起的做用同樣,都是爲這個類導入特定的.dll/.so文件用的。至於爲何不能像咱們這麼寫,我的猜想,是由於不一樣的用戶磁盤上的.dll/.so文件位置不固定,和JDK安裝目錄相關?
三、Java不在意Native方法是用什麼語言實現的,只要一來語言能和底層打 交道就行了,二來語言實現完能夠提供出來.dll/.so文件。所以同一個Native方法,若是不一樣的Java虛擬機去調用它,那麼結果可能都不一樣,比 如Object的hashCode(),固然,運行效率也不盡然相同,由於不一樣的虛擬機對於不一樣的Native方法有本身的實現。