Java 和 c/c++之间是利用什么工具进行通信的?
Posted 宸道移动安全团队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 和 c/c++之间是利用什么工具进行通信的?相关的知识,希望对你有一定的参考价值。
JNI是Java Native Interface的英文缩写,类似一种标准,提供了很多的API,使Java可以和C/C++进行通信。而JNI接口正是Java层世界与C/C++语言世界之间的桥梁。
探究:为什么使用JNI呢?
1.使用现有的开源库,现在很多优秀的开源库都是用C/C++编写的。
2.代码的保护,android APK的Java代码容易被反编译,而C/C++更难反编译。
3.便于移植,用C/C++写的库可以方便在其他嵌入式平台使用。
现在来看下面这一张图,通过这张图完美的展示JNI接口的规则。
首先看到这张图片左边部分是熟悉的Java层开发,中间部分是要用到JNI接口来调用相关的C/C++函数。那么C/C++是怎么调用Java代码的呢?这就要用到反射,在JNI接口中提供了很多函数供我们进行调用。
JNI接口是谷歌开发人员为了方便Java层与C/C++层进行通信而对外提供的接口,对应的接口描述文档在“jni.h”头文件中。
这一排就是JNI接口中的数据类型,数据类型就是在基本数据类型前加了一个字母j而已,记忆起来比较简单。如图1.1所示。
(图1.1)
紧接着是对象、数组等类型,如图1.2所示。
(图1.2)
接下来介绍JNI函数,包含的有以下几种类型,其中Call开头的函数字面意思就是调用,这里指的是通过反射调用Java层方法;Get开头的函数字面意思就是获取,这里指的是通过反射获取Java层字段的值;Set开头的函数字面意思就是设置,这里指的是通过反射修改Java层字段的值;New开头的就是创建其他类型的函数。
1. jclass (*FindClass)(JNIEnv*, const char*);
2. jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
3. jobject(*CallObjectMethod)(JNIEnv*,jobject,jmethodID, ...);
4. jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);
5. jobject (*GetObjectField)(JNIEnv*, jobject, jfieldID);
6. void (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);
7. jmethodID(*GetStaticMethodID)(JNIEnv*,jclass,const char*,constchar*);
8. jobject (*CallStaticObjectMethod)(JNIEnv*,jclass, jmethodID, ...);
9. jfieldID (*GetStaticFieldID)(JNIEnv*,jclass,const char*,const char*);
10. jobject (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID);
11. void (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject);
12. jstring (*NewStringUTF)(JNIEnv*, const char*);
接下来对上面的JNI接口函数进行了解。
(1)调用Java层普通方法
Jobject:返回值,这里返回的是jobject 。
(*CallObjectMethod):这里调用的是普通方法。
(JNIEnv*,jobject,jmethodID, ...):参数列表信息。
第一参数是JNIEnv*,是本地调用接口,里面提供大量的JNI接口函数供调用。第二个参数是jobject对象。第三个参数是方法ID,该参数可以通过GetMethodID函数获取。“...”表示的是调用方法的参数列表信息。
探究:什么是Get MethodID?
使用GetMethodID函数获取Java层的方法ID,原形如下:
jmethodID:返回值,这里返回的是Java层方法ID。
(*GetMethodID):获取普通方法ID。
(JNIEnv*, jclass, const char*, const char*):参数列表信息。
该函数的第二个参数是jclass,可以通过FindClass函数获取。第三个参数是Java层的方法名称,第四参数是Java层方法的签名信息。
探究:什么是FindClass?
FindClass函数通过反射获取Java类,原形如下:
Jclass:返回值,这里返回的是java类。
(*FindClass):反射获取Java类。
(JNIEnv*, const char*):参数列表信息。
(2)获取Java层实例字段的值
Jobject:返回值,这里返回的是jobject 。
(*GetObjectField):获取Java层实例字段的值。
(JNIEnv*, jobject, jfieldID):参数列表信息。第三参数是实例字段ID,该参数可以通过GetFieldID函数获取,原形如下:
jfieldID:返回值,这里返回的是实例字段ID。
(*GetFieldID):获取实例字段ID。
(JNIEnv*, jclass, const char*, const char*):参数信息。该函数的第三个参数是实例字段名称,第四个参数是实例字段的签名信息。
(3)设置Java层实例字段的值
Void:返回值为void。
(*SetObjectField):设置Java层实例字段的值。
(JNIEnv*, jobject, jfieldID, jobject):参数信息。第四个参数为Java层实例字段要设置的值。
(4)调用Java层静态方法。
Jobject:返回值,这里返回的是jobject 。
(*CallStaticObjectMethod):这里调用的是静态方法。
(JNIEnv*,jclass, jmethodID, ...):参数列表信息。第一参数是JNIEnv*,是本地调用接口,里面提供大量的JNI接口函数供我们调用。第二个参数是jclass。第三个参数是静态方法ID,该参数可以通过GetStatic MethodID函数获取。后面“...”表示的是调用方法的参数列表信息。
探究:什么是GetStaticMethodID?
使用GetStaticMethodID函数获取Java层的静态方法ID,原形如下:
jmethodID :返回值,这里返回的是Java层方法ID。
(*GetStaticMethodID):获取静态方法ID。
(JNIEnv*, jclass, const char*, const char*):参数列表信息。
该函数的第二个参数是jclass,可以通过FindClass函数获取。第三个参数是Java层的方法名称,第四参数是Java层方法的签名信息。
(5)获取Java层静态字段的值
Jobject:返回值,这里返回的是jobject 。
(*GetStaticObjectField):获取Java层静态字段的值。
(JNIEnv*, jclass, jfieldID): 参数列表信息。第三参数是静态字段ID,该参数可以通过GetStaticFieldID函数获取,原形如下:
jfieldID: 返回值,这里返回的是实例字段ID。
(*GetStaticFieldID): 获取静态字段ID。
(JNIEnv*, jclass, const char*, const char*): 参数信息。该函数的第三个参数是静态字段名称,第四个参数是静态字段的签名信息。
(6)设置Java层静态字段的值
void : 返回值为void。
(*SetStaticObjectField): 设置Java层静态字段的值。
(JNIEnv*, jclass, jfieldID, jobject):参数信息。第四个参数为Java层静态字段要设置的值。
(7)New开头的函数就是创建,借助new开头的函数api创建相应的基本类型、数组、对象,原形:
Jstring:返回值为jstring。
(*NewStringUTF) :创建utf-8编码的字符串。
(JNIEnv*, const char*):参数列表信息。第二个就是参数是char*类型的值,在这里可以输入想要创建的字符串。
本次主要分享了JNI接口是实现Java层与C/C++层相互调用,以及常用的JNI接口函数和它们的用途,如下表所示。
以上是关于Java 和 c/c++之间是利用什么工具进行通信的?的主要内容,如果未能解决你的问题,请参考以下文章