[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字节。

相关文章
|
Java API Android开发
[NDK/JNI系列01] NDK与JNI的基本概念与使用场景
[NDK/JNI系列01] NDK与JNI的基本概念与使用场景
406 0
|
7月前
|
机器学习/深度学习 人工智能 负载均衡
Trae 04.22版本深度解析:Agent能力升级与MCP市场对复杂任务执行的革新
在当今快速发展的AI技术领域,Agent系统正成为自动化任务执行和智能交互的核心组件。Trae作为一款先进的AI协作平台,在04.22版本中带来了重大更新,特别是在Agent能力升级和MCP市场支持方面。本文将深入探讨这些更新如何重新定义复杂任务的执行方式,为开发者提供更强大的工具和更灵活的解决方案。
797 1
|
9月前
|
人工智能 弹性计算 运维
|
存储 Java
如何在 Java 中写入和读取 ByteBuffer
【8月更文挑战第22天】
476 0
|
Java API Android开发
[NDK/JNI系列04] JNI接口方法表、基础API与异常API
[NDK/JNI系列04] JNI接口方法表、基础API与异常API
291 0
|
传感器 Java 开发工具
[NDK/JNI系列03] Android Studio集成NDK开发环境
[NDK/JNI系列03] Android Studio集成NDK开发环境
184 0
|
算法 安全 编译器
理解和记忆std::atomic
理解和记忆std::atomic
232 0
|
小程序 JavaScript 前端开发
4大主流小程序平台介绍及其优缺点对比
小程序是一种轻量级应用程序,能够在手机上直接运行,无需下载安装,适用于一些简单的功能场景,如点餐、预约、查看天气等。以下是目前主流的小程序平台及其优缺点对比
3596 0
|
Linux Docker 索引
Docker---Docker 在CentOS上安装
Docker---Docker 在CentOS上安装
Docker---Docker 在CentOS上安装
|
小程序 JavaScript 前端开发
ssm+vue基本微信小程序的个人健康管理系统
首先,论文一开始便是清楚的论述了小程序的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了小程序的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项目软件架构选择B/S模式,总体功能模块运用自顶向下的分层思想。再然后就是实现系统并进行代码编写实现功能。论文的最后章节总结一下自己完成本论文和开发本项目的心得和总结。
340 0