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


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

原文鏈接:http://www.2cto.com/kf/201405/302263.html

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

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這些奇形怪狀的表示形式也有一定的了解了。

結束。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM