[NDK/JNI系列02] JNI的设计原理与数据类型

简介: [NDK/JNI系列02] JNI的设计原理与数据类型

这些概念脑子过一遍 , 实际上是记不住的 , 只能记录下来查缺补漏 , 通过实战去强化记忆。

JNI的设计原理和代码示例

JNI是Java Native Interface的缩写,是Java提供的一套标准接口,可以让Java代码和其他语言(如C或C++)编写的代码进行交互。JNI定义了一套规范,包括数据类型、函数签名、命名规则等,以保证不同语言之间的兼容性和可移植性。

JNI的设计原理主要包括以下几个方面:

1. JNIEnv

JNI使用了一个中间层,即JNIEnv,来封装Java虚拟机(JVM)和本地代码之间的通信。JNIEnv是一个指向函数表的指针,提供了大量的JNI函数,可以让本地代码访问和操作JVM中的对象、方法、字段等。JNIEnv是线程相关的,每个线程都有自己的JNIEnv,不能在不同线程之间共享。

JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj){
  // 使用env来访问和操作JVM
}

2. JNI数据类型

JNI使用了一些特殊的数据类型,来表示Java中的数据类型在本地代码中的映射。对于基本类型,JNI和Java之间的映射是一对一的,例如Java中的int类型对应于C/C++中的jint类型。对于引用类型,JNI把Java中的对象当作一个C指针传递到本地函数中,这个指针指向JVM中的内部数据结构,而内部数据结构在内存中的存储方式是不可见的,本地代码必须通过JNIEnv中选择适当的JNI函数来操作JVM中的对象。

JNIEXPORT jint JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jint x, jint y){
  // 使用jint来表示Java中的int类型
  return x + y;
}

3. JNI标识符

JNI使用了一些特殊的标识符,来表示Java中的方法和字段在本地代码中的引用。这些标识符分别是jmethodID和jfieldID,它们通常是指向内部运行时数据结构的指针。本地代码需要通过JNIEnv中提供的函数来获取这些标识符,然后才能调用或访问相应的方法或字段。

JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj){
  jclass cls = (*env)->GetObjectClass(env, obj);
  jmethodID mid = (*env)->GetMethodID(env, cls, "methodName", "(I)V");
  if (mid == NULL) {
    return; /* method not found */
  }
  (*env)->CallVoidMethod(env, obj, mid, 123);
}

4. JNI方法签名

JNI使用了一个特殊的字符串格式,来表示Java中方法的签名。这个字符串格式包含了方法参数和返回值的类型信息,以便本地代码能够正确地调用Java方法。例如,一个Java方法public int add(int x, int y)在JNI中的签名是"(II)I",表示该方法有两个int类型的参数和一个int类型的返回值。

JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj){
  jclass cls = (*env)->GetObjectClass(env, obj);
  jmethodID mid = (*env)->GetMethodID(env, cls, "add", "(II)I");
  if (mid == NULL) {
    return; /* method not found */
  }
  jint result = (*env)->CallIntMethod(env, obj, mid, 1, 2);
}

以上代码示例展示了如何在C/C++代码中使用JNIEnv、JNI数据类型、JNI标识符和JNI方法签名。

 

JNI调用Java方法和Java调用JNI方法的流程:

5.JNI的数据类型

JNI的数据类型主要分为两类:基本类型和引用类型。

1. 基本类型

基本类型是指Java中的八种基本数据类型,包括int、boolean等。JNI的基本类型和Java中的基本类型是一一对应的,

它在C/C中都有相应的别名,以j开头,例如jint表示int类型,jboolean表示boolean类型等。JNI的基本类型和C/C中的基本类型在内存中的表示方式是相同的,所以可以直接进行赋值和运算,不需要进行转换。

JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jint x, jboolean y){
  // 使用jint和jboolean来表示Java中的int和boolean类型
  // 可以直接进行赋值和运算
  jint z = x + 1;
  jboolean b = !y;
}
2. 引用类型

引用类型是指Java中的对象、数组、字符串等。JNI的引用类型和Java中的引用类型是不完全对应的,它们在C/C中都是指针类型,以j开头,例如jobject表示任意对象类型,jstring表示字符串类型等。JNI的引用类型和C/C中的指针类型在内存中的表示方式是不同的,所以不能直接进行赋值和运算,需要通过JNIEnv中提供的函数来进行转换和操作。

JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jstring str){
  // 使用jstring来表示Java中的String类型
  // 需要通过JNIEnv中提供的函数来进行转换和操作
  const char *c_str = (*env)->GetStringUTFChars(env, str, 0);
  // 使用c_str
  (*env)->ReleaseStringUTFChars(env, str, c_str);
}

下表列出了JNI中常用的数据类型及其含义:

JNI数据类型

Java数据类型

C/C++数据类型

JNI签名字符

内存大小(字节)64/32位系统

含义

jboolean

boolean

unsigned char

Z

1

布尔值

jbyte

byte

signed char

B

1

字节

jchar

char

unsigned short

C

2

字符

jshort

short

short

S

2

短整数

jint

int

int

I

4

整数

jlong

long

long long

J

8

长整数

jfloat

float

float

F

4

单精度浮点数

jdouble

double

double

D

8

双精度浮点数

jobject

Object

_jobject*

L

8/ 4

任意对象

jclass

Class<?>

_jclass*

L

8/ 4

类对象

jstring

String

_jstring*

Ljava/lang/String;

8/ 4

字符串对象

jarray

Object[]

_jarray*

[

8/ 4

任意数组

jbooleanArray

boolean[]

_jbooleanArray*

[Z

8/ 4

布尔数组

jbyteArray

byte[]

_jbyteArray*

[B

8/ 4

字节数组

jcharArray

char[]

_jcharArray*

[C

8/ 4

字符数组

jshortArray

short[]

_jshortArray*

[S

8/ 4

短整数数组

jintArray

int[]

_jintArray*

[I

8/ 4

整数数组

jlongArray

long[]

_jlongArray*

[J

8/ 4

长整数数组

jfloatArray

float[]

_jfloatArray*

[F

8/ 4

单精度浮点数数组

jdoubleArray

double[]

_jdoubleArray*

[D

8/ 4

双精度浮点数数组

在JNI签名中,基本类型由单个字符表示,对象类型由'L'开始,由';'结束,数组类型由'['开始。例如,jstring在JNI签名中表示为"Ljava/lang/String;",表示它是一个String对象。


请注意,引用类型(如jobject、jclass、jstring等)在内存中的大小取决于你的系统是32位还是64位。在32位系统中,所有的引用类型都是4字节;在64位系统中,所有的引用类型都是8字节。

相关文章
|
6月前
|
Java API Android开发
[NDK/JNI系列01] NDK与JNI的基本概念与使用场景
[NDK/JNI系列01] NDK与JNI的基本概念与使用场景
68 0
|
6月前
|
缓存 Java API
[NDK/JNI系列05] JNI引用API
[NDK/JNI系列05] JNI引用API
55 0
|
Java Unix Linux
JNI学习(0)——关于JNI
JNI学习(0)——关于JNI
139 0
JNI学习(0)——关于JNI
|
Java
JNI学习(3)——运行基于JNI的java程序
JNI学习(3)——运行基于JNI的java程序
96 0
JNI学习(3)——运行基于JNI的java程序
JNI中访问JList的代码
JNI中访问JList的代码
63 0
|
Linux 编译器 Android开发
【Android NDK 开发】JNI 方法解析 ( JNIEXPORT 与 JNICALL 宏定义作用 )
【Android NDK 开发】JNI 方法解析 ( JNIEXPORT 与 JNICALL 宏定义作用 )
601 0
|
Java C语言 Windows