【转】对于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这些奇形怪状的表示形式也有必定的了解了。 结束。
相关文章
相关标签/搜索