android中不少Java類都具備native接口,這些接口由本地實現,而後註冊到系統中。
主要的JNI代碼放在如下的路徑中:frameworks/base/core/jni/,這個路徑中的內容被編譯成庫 libandroid_runtime.so,被放置在目標系統的/system/lib目錄下。此外,android還有其餘的 JNI庫。JNI中的各個文件,實際上就是普通的C++源文件.
若是要深刻了解android framework層,則必須Android Native層運行及開發機制.
這裏先介紹一些native的基礎知識java
一、接口定義
_JNIEnv定義了一個虛擬機的接口,經過這個接口能夠訪問虛擬機的全部功能:
1)分配對象(AllocObject/NewObject),而且控制對象的引用計數(NewGlobalRef/DeleteGlobalRef/DeleteLocalRef/IsSameObject/NewLocalRef)。
2)獲取類的定義(FindClass),並經過類的定義來獲取獲取類得方法和成員的ID(GetMethodID/GetFieldID)
3)經過方法ID調用類的普通方法(CallObjectMethod)和靜態方法(CallStaticObjectMethod)
4)經過成員ID獲取和設置類的普通成員(GetObjectField/SetObjectField)和靜態成員(GetStaticObjectField/SetStaticObjectField)
下面是比較經常使用的方法:
1)查找該類:
jclass xxx = (*env)->FindClass(env, "Lclass_name;");
2)取得方法的id:
jmethodID xxx = (*env)->GetMethodID(env, jclass, methodName, "(M)N");
3)查找須要調用的該類的方法:
jmethodID xxx = (*env)->GetMethodID(env, jclass, "(M)N" );
4)取得靜態方法的id
jmethodID xxx = (*env)->GetStaticMethodID(env,jclass, methodName,"(M)N")
5)初始化該類的實例:
jobject xxx = (*env)->NewObject(env, jclass, jmethodID );
6)調用實例的某方法:
(*env)->CallObjectMethod(env, jobject, jmethodID, [parameter1, parameter2,...] );
7)釋放實例:
(*env)->DeleteLocalRef(env, xxx);
8)取得成員變量的id
jfieldID xxx = (*env)->GetFieldID(env,jclass ,jfieldID,jfieldType)
9)取得靜態成員變量的id
jfieldID xxx = GetStaticFieldID(env,jclass ,jfieldID,jfieldType)
JNIENV - java的運行環境
jobject - 表明java的instance
jclass - 表明java的類android
二、函數與屬性簽名
在GetMethodID和GetFieldID這兩個函數中,最後一個參數都是簽名字符串,用來標示java函數和成員的惟一性。
由於java中存在重載函數,因此一個函數名不足以惟一指定一個函數,這時候就須要簽名字符串來指定函數的參數列表和返回值類型了。
函數簽名是一個字符串:"(M)N"
括號中的內容是函數的參數類型,括號後面表示函數的返回值。數組
三、JNI 類型簽名
"(M)N",這裏的M和N指的是該函數的輸入和輸出參數的類型簽名(Type Signature)。
具體的每個字符的對應關係以下
字符 Java類型 C類型
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
數組則以」["開始,用兩個字符表示
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
若是Java函數的參數是class,則以」L」開頭,以」;」結尾,中間是用」/」 隔開的包及類名。而其對應的C函數名的參數則爲jobject
一個例外是String類,其對應的類爲jstring
Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject
若是JAVA函數位於一個嵌入類,則用$做爲類名間的分隔符。
例如 「(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z」
舉例說明"(M)N"的含義,例如:
(I)V 帶一個int 類型的參數,返回值類型爲void
()D 沒有參數,返回double函數
本文歡迎轉載,但請註明做者與出處:對象
做者:流星blog