JNI学习笔记:JNI数据类型和数据结构



0. 前言

Java与C++代码的交互都是通过native函数来完成,而使用函数,必然会牵涉到数据传递,数据类型决定了内存中数据的解释方式,不同的语言之间会有所不同,因此两者之间的交互,要遵守一定规则。在Java中,数据类型可以分为基本类型和引用类型,这与C++有些微不同,那么两者之间如何转换呢?Oracle官方文档给出了相关解释,本文是对官方文档的翻译和整理。

1. 基本类型

java和C++的基本数据类型,是可以直接转换的,仅在名字上有所区别。

Java类型 Native类型 描述
boolean jboolean 8位无符号数
byte jbyte 8位有符号数
char jchar 16位无符号数
short jshort 16位有符号数
int jint 32位有符号数
long jlong 64位有符号数
float jfloat 32位
double jdouble 64位
void void N/A

其中,jsize和jint是同义词,jsize多用于循环计数,有如下定义

typedef jint jsize; 

还有两个常量用来表示布尔值,方便使用

#define JNI_FALSE  0 
#define JNI_TRUE   1

从名字上看,不难看出,从Java层面传值的基本类型,在JNI中的Native代码仅仅是在类型名前面加了一个j前缀。需要特别指出的是,C/C++代码依赖于编译器的具体编译和解释,因此在不同的编译器上,可能会有所不同。

2. 引用类型

2.1 引用类型层次结构

JNI包括许多与不同种类的Java对象对应的引用类型。JNI引用类型的层次结构如图所示。
JNI引用类型的层次结构

在C语言中,所有的JNI引用类型被统一定义为jobject,如:

typedef jobject jclass

在C++中,JNI引入了虚拟类(dummy classes)描述子类之间的关系,如下:

class _jobject {}; 
class _jclass : public _jobject {}; 
... 
typedef _jobject *jobject; 
typedef _jclass *jclass;

JNI中对本地引用类型的定义是通过指针来操作的,但是如果想通过JNI接口进行传值,如:在函数中传递数组或者对象等,还需要相关的JNI函数进行配合使用。

2.2 字段和方法

本地代码(C/C++)如果要调用Java中的对象方法,也就是通常所说的来自本地方法的回调(callback),需要用到JNI中的字段和方法
JNI中对字段和方法的定义如下

struct _jfieldID;              /* opaque structure */ 
typedef struct _jfieldID *jfieldID;   /* field IDs */ 

struct _jmethodID;              /* opaque structure */ 
typedef struct _jmethodID *jmethodID; /* method IDs */

2.3 值类型

jvalue枚举类型通常用作参数数组中的类型元素,定义如下:

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

2.4 类型签名

JNI使用Java的类型签名表示方法,详情如下表:

类型签名 Java类型
Z Boolean
B byte
C char
S short
I int
J long
F float
D double
L 完全限定名 完全限定名
[类型 该类型的数组
(参数)类型 对应方法

方法签名主要是为了解决函数重载造成的重名问题的,通过对不同的类型进行标记,从而区别不同的重载方法。

例如,存在如下Java方法声明:

long f (int n, String s, int[] arr); 

其对应的JNI类型签名为

(ILjava/lang/String;[I)J 

猜你喜欢

转载自blog.csdn.net/cv_jason/article/details/79629425
今日推荐