因为Java支持函数重载(方法名一样但是参数不一样),所以在JNI层要想确定Java层的方法,必须有一个标准把方法和参数都定义进去,这样JNI才能知道它要调用的是哪个Java方法。而JNI方法签名就是这个标准。
先来看一下基本数据类型的签名:
Java基本类型 | 签名 |
---|---|
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
void | V |
可以看到,基本数据类型签名一般是首字母的大写,boolean例外,是因为B已经被 byte占用。long的标签之所以不是L,是因为L表示的是类的签名。
类的签名比较简单,它采用”L+包名+类名+;”的形式,只需要将其中的 . 替换成 / 即可。比如java.lang.String,它的签名为 Ljava/lang/String;,末尾的 ; 也是签名的一部分。
对象的签名就是它所属的类的签名,比如String对象,它的签名就是String类的签名,即 Ljava/lang/String;。
数组的签名为 [+类型签名,比如int数组,其类型为int,而int的签名为 I ,所以int数组的类型签名就是 [I,同理可以得到如下的签名对应关系:
数组 | 签名 |
---|---|
char[] | [C |
float[] | [F |
double[] | [D |
long[] | [J |
String[] | [Ljava/lang/String; |
Object[] | [Ljava/lang/Object; |
方法的签名为(参数的类型签名)+返回值类型签名。
举例说明,如下方法:
1 | int add(int a, int b) |
参数的类型签名连在一起是 II,返回值类型签名是 I,所以整个方法的签名就是 (II)I。再举个复杂点的例子,如下方法:
1 | String fun(int a, String b, int[] c) |
整个方法的签名就是 (ILjava/lang/String;[I)Ljava/lang/String;。