Java -- JNI中的数据类型

Java -- JNI中的数据类型

 

JNI,即Java Native Interface,意为Java本地调用。JNI是一种Java技术,通过使用JNI,我们不仅可以在Java代码里调用C/C++实现的native方法,也可以在native代码里面调用Java实现的方法。从这里大概也可以得出,JNI的出现,一个重要的原因就是“避免重复造轮子“,提高代码复用性。Android framework中,JNI的使用频率非常高;Java层实现业务逻辑、流程控制,再通过JNI调用native方法来完成具体的业务实现。

在Android平台上,JNI就是一座将Native世界和Java世界的天堑变成通途的桥梁。Android平台上JNI所处的位置: Java世界 <--> JNI层 <--> Native世界(引用)。

在JNI中,Java层面的数据类型和引用类型都是不能直接被解析的。即使向JNI传递的是一个简单的int类型,它也不能被直接识别,必须进行相应的类型转换,转换成JNI中与之对应的类型。

下面主要介绍Java和JNI中的类型映射关系。

Java中存在的基本数据类型,在JNI中都有一种特殊的类型与之对应:

类型映射
Java类型native类型类型描述(C/C++)
bytejbyte有符号的8位整型
charjchar无符号的16位整型
shortjshort带符号的16位整型
intjint带符号的32位整型
longjlong带符号的64位整型
floatjfloat32位浮点型
doublejdouble64位浮点型
booleanjboolean无符号的8位整型

这些基本数据类型都是可以在native层直接使用的 。不过,务必注意转化成native类型后对应数据类型的字长,例如jchar在native语言中是16位,占两个字节,这和普通的char占一个字节是完全不一样的。其次,Java中void的native类型依旧是void。

类似的,Java中的引用数据类型,在JNI中也有一种特殊的类型与之对应:

类型映射
Java类型native类型类型描述
java.lang.Objectjobject任何Java对象,或者没有对应Java类型的对象
java.lang.Stringjstring字符串对象
java.lang.ClassjclassClass对象
java.lang.ThrowablejthrowableThrowable对象
Object[]jobjectArray任意类型的对象数组
byte[]jbyteArraybyte类型数组
char[]jcharArraychar类型数组
short[]jshortArrayshort类型数组
int[]jintArrayint类型数组
long[]jlongArraylong类型数组
float[]jfloatArrayfloat类型数组
double[]jdoubleArraydouble类型数组
boolean[]jbooleanArray布尔类型数组


我们要通过Java层声明的native类型方法,例如:

 public native static boolean startDhcp(String interfaceName);

通过JNI调用到native实现(C/C++),必须要有一种联系,将这两类方法连接起来。考虑到Java支持函数重载,JNI选择函数的签名信息(参数列表、返回值)作为连接Java native类型方法和native实现方法的桥梁。有了函数名和它的签名信息,就可以很方便的找到所需的函数了。同样地,在JNI函数签名信息中,也存在对应的类型映射关系:

类型映射
Java类型类型签名
boolean    Z
byte    B
char    C
short    S
int    I
long    J
float    F
double    D
void    V
L + 全限定名,String的类型签名是"Ljava/lang/String;"包括最后的分号
数组[  + 类型签名,byte[]的类型签名是"'[B";"[java/lang/Object;"的Java类型是Object[]
函数声明"(参数1,参数2,...)返回值类型"

请注意,如果Java类型是数组,则标识中会有一个“[”,另外,引用类型(除基本类型的数组外)的标识最后都有一个“;”。

下面从Android源码中,列举一些JNI函数签名的示例:

函数签名映射
Java函数声明JNi函数签名
int resetConnections(String interfaceName, int mask)"(Ljava/lang/String;I)I"
boolean startDhcp(String interfaceName)"(Ljava/lang/String;)Z"
boolean getDhcpResults(String interfaceName, DhcpResults dhcpResults)"(Ljava/lang/String;Landroid/net/DhcpResults;)Z"
int bindSocketToNetwork(int socketfd, int netId)"(II)I"
String getDhcpError()"()Ljava/lang/String;"

函数的返回值类型出现在函数签名参数列表括号的右侧。

最后JNI中还定义了一个jvalue类型:

typedef union jvalue { 
    jboolean z; 
    jbyte    b; 
    jchar    c; 
    jshort   s; 
    jint     i; 
    jlong    j; 
    jfloat   f; 
    jdouble  d; 
    jobject  l; 
} jvalue; 

这个union类型经常作为JNI中参数数组的元素类型:

static void android_animation_PropertyValuesHolder_callMultipleFloatMethod(
        JNIEnv* env, jclass pvhObject, jobject target, jlong methodID, jfloatArray arg)
{
    jsize parameterCount = env->GetArrayLength(arg);
    jfloat *floatValues = env->GetFloatArrayElements(arg, NULL);
    jvalue* values = new jvalue[parameterCount];
    for (int i = 0; i < parameterCount; i++) {
        values[i].f = floatValues[i];
    }
    env->CallVoidMethodA(target, reinterpret_cast<jmethodID>(methodID), values);
    delete[] values;
    env->ReleaseFloatArrayElements(arg, floatValues, JNI_ABORT);
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值