1. 程式人生 > >入瞭解android平臺的jni(一)

入瞭解android平臺的jni(一)

android中很多Java類都具有native介面,這些介面由本地實現,然後註冊到系統中,主要的JNI程式碼放在以下的路徑中:frameworks/base/core/jni/,這個路徑中的內容被編譯成庫 libandroid_runtime.so,被放置在目標系統的/system/lib目錄下。此外,android還有其他的 JNI庫。JNI中的各個檔案,實際上就是普通的C++原始檔。如果要深入瞭解android framework層,則必須學習Android Native層執行及開發機制,這裡先介紹一些native的基礎知識。

1、介面定義
       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的類


2、函式與屬性簽名
       在GetMethodID和GetFieldID這兩個函式中,最後一個引數都是簽名字串,用來標示java函式和成員的唯一性。因為java中存在過載函式,所以一個函式名不足以唯一指定一個函式,這時候就需要簽名字串來指定函式的引數列表和返回值型別了。函式簽名是一個字串:"(M)N",括號中的內容是函式的引數型別,括號後面表示函式的返回值。


3、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

本文歡迎轉載,但請註明作者與出處:

作者:流星