如何使用JNI的一些基本方法和過程在網上多如牛毛,若是你對Jni不甚瞭解,不知道Jni是作什麼的,如何創建一個基本的jni程序,或許能夠參考下面下面這些文章:
利用VC++6.0實現JNI的最簡單的例子
JNI入門教程之HelloWorld篇
SUN JNI Tutorial
這些資料的例子中,大多數只是輸入一些簡單的參數,獲取沒有參數。而在實際的使用過程當中,每每須要對參數進行處理轉換。才能夠被C/C++程序識別。好比咱們在C++中有一個結構(Struct)DiskInfo ,須要傳遞一個相似於DiskInfo *pDiskInfo的參數,相似於在C++這樣參數如何傳遞到Java中呢?下面咱們就來討論C++到Java中方法的一些常見參數的轉換:
html
若是你習慣了使用JNI,你就不會以爲它難了。既然本地方法是由其餘語言實現的,它們在Java中沒有函數體。可是,全部本地代碼必須用本地關鍵詞聲明,成爲Java類的成員。假設咱們在C++中有這麼一個結構,它用來描述硬盤信息: java
那麼咱們須要在Java中定義一個類來與之匹配,聲明能夠寫成這樣: web
在這個類中,申明一些Native的本地方法,來測試方法參數的傳遞,分別定義了一些函數,用來傳遞結構或者結構數組,具體定義以下面代碼: windows
編譯生成C/C++頭文件
定義好了Java類以後,接下來就要寫本地代碼。本地方法符號提供一個知足約定的頭文件,使用Java工具Javah能夠很容易地建立它而不用手動去建立。你對Java的class文件使用javah命令,就會爲你生成一個對應的C/C++頭文件。
一、在控制檯下進入工做路徑,本工程路徑爲:E:\work\java\workspace\JavaJni。
二、運行javah 命令:javah -classpath E:\work\java\workspace\JavaJni com.sundy.jnidemo ChangeMethodFromJni
本文生成的C/C++頭文件名爲: com_sundy_jnidemo_ChangeMethodFromJni.h
在C/C++中實現本地方法
生成C/C++頭文件以後,你就須要寫頭文件對應的本地方法。注意:全部的本地方法的第一個參數都是指向JNIEnv結構的。這個結構是用來調用JNI函數的。第二個參數jclass的意義,要看方法是否是靜態的(static)或者實例(Instance)的。前者,jclass表明一個類對象的引用,然後者是被調用的方法所屬對象的引用。 數組
返回值和參數類型根據等價約定映射到本地C/C++類型,如表JNI類型映射所示。有些類型,在本地代碼中可直接使用,而其餘類型只有經過JNI調用操做。 eclipse
表A jvm
Java類型 | 本地類型 | 描述 |
boolean | jboolean | C/C++8位整型 |
byte | jbyte | C/C++帶符號的8位整型 |
char | jchar | C/C++無符號的16位整型 |
short | jshort | C/C++帶符號的16位整型 |
int | jint | C/C++帶符號的32位整型 |
long | jlong | C/C++帶符號的64位整型e |
float | jfloat | C/C++32位浮點型 |
double | jdouble | C/C++64位浮點型 |
Object | jobject | 任何Java對象,或者沒有對應java類型的對象 |
Class | jclass | Class對象 |
String | jstring | 字符串對象 |
Object[] | jobjectArray | 任何對象的數組 |
boolean[] | jbooleanArray | 布爾型數組 |
byte[] | jbyteArray | 比特型數組 |
char[] | jcharArray | 字符型數組 |
short[] | jshortArray | 短整型數組 |
int[] | jintArray | 整型數組 |
long[] | jlongArray | 長整型數組 |
float[] | jfloatArray | 浮點型數組 |
double[] | jdoubleArray | 雙浮點型數組 |
※ JNI類型映射
ide
JNI經過JNIEnv提供的操做Java數組的功能。它提供了兩個函數:一個是操做java的簡單型數組的,另外一個是操做對象類型數組的。 函數
由於速度的緣由,簡單類型的數組做爲指向本地類型的指針暴露給本地代碼。所以,它們能做爲常規的數組存取。這個指針是指向實際的Java數組或者Java數組的拷貝的指針。另外,數組的佈置保證匹配本地類型。 工具
爲了存取Java簡單類型的數組,你就要要使用GetXXXArrayElements函數(見表B),XXX表明了數組的類型。這個函數把Java數組當作參數,返回一個指向對應的本地類型的數組的指針。
表B
函數 | Java數組類型 | 本地類型 |
GetBooleanArrayElements | jbooleanArray | jboolean |
GetByteArrayElements | jbyteArray | jbyte |
GetCharArrayElements | jcharArray | jchar |
GetShortArrayElements | jshortArray | jshort |
GetIntArrayElements | jintArray | jint |
GetLongArrayElements | jlongArray | jlong |
GetFloatArrayElements | jfloatArray | jfloat |
GetDoubleArrayElements | jdoubleArray | jdouble |
JNI數組存取函數
當你對數組的存取完成後,要確保調用相應的ReleaseXXXArrayElements函數,參數是對應Java數組和GetXXXArrayElements返回的指針。若是必要的話,這個釋放函數會複製你作的任何變化(這樣它們就反射到java數組),而後釋放全部相關的資源。
爲了使用java對象的數組,你必須使用GetObjectArrayElement函數和SetObjectArrayElement函數,分別去get,set數組的元素。GetArrayLength函數會返回數組的長度。
JNI提供的另一個功能是在本地代碼中使用Java對象。經過使用合適的JNI函數,你能夠建立Java對象,get、set 靜態(static)和實例(instance)的域,調用靜態(static)和實例(instance)函數。JNI經過ID識別域和方法,一個域或方法的ID是任何處理域和方法的函數的必須參數。
表C列出了用以獲得靜態(static)和實例(instance)的域與方法的JNI函數。每一個函數接受(做爲參數)域或方法的類,它們的名稱,符號和它們對應返回的jfieldID或jmethodID。
表C
函數 | 描述 |
GetFieldID | 獲得一個實例的域的ID |
GetStaticFieldID | 獲得一個靜態的域的ID |
GetMethodID | 獲得一個實例的方法的ID |
GetStaticMethodID | 獲得一個靜態方法的ID |
※域和方法的函數
若是你有了一個類的實例,它就能夠經過方法GetObjectClass獲得,或者若是你沒有這個類的實例,能夠經過FindClass獲得。符號是從域的類型或者方法的參數,返回值獲得字符串,如表D所示。
表D
Java 類型 | 符號 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | L |
float | F |
double | D |
void | V |
objects對象 | Lfully-qualified-class-name;L類名 |
Arrays數組 | [array-type [數組類型 |
methods方法 | (argument-types)return-type(參數類型)返回類型 |
※肯定域和方法的符號