【轉】對於JNI方法名,數據類型和方法簽名的一些認識

以前一直用jni,可是沒有考慮Java重載函數,如何在jni-C++裏命名,今天看到一篇文章,講到了類型簽名。html

原文連接:http://www.2cto.com/kf/201405/302263.htmljava

咱們知道,利用javah生成的c/c++頭文件的時候,會對java中定義的 native 函數生成對應的jni層函數,以下:c++

1
2
3
4
5
6
7
/*
  * Class:     com_lms_jni_JniTest
  * Method:    getTestString
  * Signature: ()Ljava/lang/String;
  */ 
JNIEXPORT jstring JNICALL Java_com_lms_jni_JniTest_getTestString 
   (JNIEnv *, jobject);

咱們能夠看到方法名是以Java_com_lms_jni等開頭的,還有什麼所謂的Signature,那這些其實都是什麼意思呢,今天咱們就來簡單地認識一下。

JNI 命名規則

對於傳統的JNI編程來講,JNI方法跟Java類方法的名稱之間有必定的對應關係,要遵循必定的命名規則,以下:
編程

1) 前綴: Java_
2) 類的全限定名,用下劃線進行分隔(_):com_lms_jni_JniTest
3) 方法名:getTestString
3) jni函數指定第一個參數: JNIEnv *
4) jni函數指定第二個參數: jobject
5) 實際Java參數: jstring, jint ....
6) 返回值的參數 : jstring, jint.... 因此對於在Java類 com.lms.jni.HwDemo中的一個方法:
?
1
public native String addTail(String tail);

其對應的jni層的方法以下:
?
1
jstring Java_com_lms_jni_HwDemo_addTail(JNIEnv * e, jobject clazz, jstring tail);

若是不這樣命名,當把動態庫加載進DVM的時候,經過JNIEnv *指針去查找Java Native方法對應的JNI方法的時候,就會找不到了。
注意,咱們也能夠利用函數註冊的方法,將Java層的方法名跟JNI層的方法名的對應關係保存起來,註冊到DVM中,就不須要這樣的命名規範了。

JNI 數據類型


咱們知道Java的數據類型是跟C/C++的數據類型是不同的,而JNI是處於Java和Native本地庫(大部分是用C/C++寫的)中間的一層,JNI對於兩種不一樣的數據類型之間必須作一種轉換,因此在JNI跟Java之間就會有數據類型的對應關係。 在JNI中,提供瞭如下各類數據類型,能夠分爲原生類型和引用類型: 對於原生類型有:jchar, jbyte, jshort, jint, jlong, jfloat, jdouble, jboolean,其與java端的數據類型對應以下表:
java jni
char jchar
byte jbyte
short jshort
int jint
long jlong
float jfloat
double jdouble
boolean jboolean

對於引用類型則有:jobject, jstring, jthrowable, jclass, jarray, 以及繼承於jarray,對應於其原生類型的8種jarray和jobjectarray。
\

知道了不一樣的數據類型的轉換關係,咱們就知道在什麼狀況下,應該對數據進行怎麼樣的處理。

JNI方法簽名



爲何會有方法簽名這種東西呢?這是由於Java這邊支持函數重載,即雖然參數不同,可是方法名同樣,那麼在JNI層它們的方法名都會是同樣的,那JNI也會犯迷糊了,得找哪一個呢?
不過也正是由於其參數類型是不同的,因此就出現了方法簽名,利用方法簽名和方法名來惟一肯定一個JNI函數的調用。
既然方法簽名是基於參數類型的不一樣而造成的,首先要知道Java各數據類型對應的簽名是什麼,也就是所謂的類型簽名,
在jni.h文件中就已經定義了這樣一套規則,以下:
?
1
2
3
4
5
6
7
8
9
10
11
typedef union jvalue {
     jboolean    z;
     jbyte       b;
     jchar       c;
     jshort      s;
     jint        i;
     jlong       j;
     jfloat      f;
     jdouble     d;
     jobject     l;
} jvalue;

對應於Java端的數據類型,咱們也能夠看一下下面的表:
Java 類型 類型簽名
boolean Z
byte B
char C
short S
int I
long L
float F
double D
L全限定名;,好比String, 其簽名爲Ljava/lang/util/String;
數組 [類型簽名, 好比 [B

對於上面的類,要注意其後面還有一個分號。
而對一個方法,其簽名就是其參數類型簽名和返回值類型簽名的字符串,其形式以下:
(類型簽名1類型簽名2...)返回值類型簽名
每一個類型簽名之間是沒有空格的,下面看看兩個例子:

有方法 1):
?
1
public string addTail(String tail, int index)

其對應的簽名以下:
?
1
(Ljava/util/String;I)Ljava/util/String;

方法 2):
?
1
public int addValue( int index, String value, int [] arr)

其對應的簽名以下:
?
1
(ILjava/util/String;[I)I
相信經過這兩個例子,你們也可以瞭解了方法簽名是什麼樣的形式了吧,對於JNI這些奇形怪狀的表示形式也有必定的瞭解了。 結束。
相關文章
相關標籤/搜索