内构函数java_Android JNI参数传递

Java中调用native函数传递的参数是Java数据类型,到了JNI层需进行数据类型转换,基本数据类型是在前面加个j,如int——>jint,应用数据类型除了基本数据类型的数据、Class、String和Throwable外,其余所有Java对象的数据类型在JNI中都用jobject表示。

//Java层com.xxx.yyy包MyJni.java中的jnitest有三个参数

jnitest(String path, String name, MyJni mj);

//JNI层对应的函数的后三个参数与jnitest的参数对应

com_xxx_yyy_MyJni_jnitest(JNIEnv *env, jobject thiz, jstring path, jstring name, jobject mj);

若对象类型都用就object表示,就好比是native层的void* 类型一样。第二个参数就object代表Java层的实例对象,如果Java层是static函数,则这个参数将是jclass,表示在调用哪个Java Class的静态函数。

JNIEnv介绍

JNIEnv是一个与线程相关的代表JNI环境的结构体,内部结构如图:

0818b9ca8b590ca3270a3433284dd417.png

从上图可知JNIEnv提供了一些JNI系统函数:

调用Java的函数

操作jobejct对象等很多事情

每个线程都有一个JNIEnv,由于线程相关,所以一个线程不能使用另一个线程的JNIEnv结构体。JNIEnv是native函数转换成JNI层函数后有虚拟机传进来的,但当后台线程收到一个网络消息,且需有native层函数主动回调Java层函数时,JNIEnv如何传递?

这就要用到JavaVM,它是虚拟机在JNI层的代表,如下:

//全进程只有一个JavaVM对象,可保存且在任何地方都可使用

jint JNI_OnLoad(JavaVM* vm, void* reserved);

而JavaVM 和 JNIEnv的关系如下:

调用JavaVM的AttachCurrentThread函数,就可得到这个线程的JNIEnv结构体,即可在后台回调Java函数。

在后台线程退出前,需调用JavaVM的DetachCurrentThread函数释放对应的资源。

通过JNIEnv操作jobject

Java引用类型除了少数几个外,其余在JNI层都会用jobject来表示对象的数据类型,操作jobject的本质是操作Java对象的成员变量和成员函数。

jfieldID 和 jmethodID 介绍

JNI规则中用jfieldID 和 jmethodID表示Java类的成员变量和成员函数,可通过JNIEnv的函数得到:

jfieldID GetFieldID(jclass clazz, const char *name, const char *sig);

jmethodID GetMethodID(jclass clazz, const char *name, const char *sig);

其中,jclass表示Java类,name表示成员函数或成员变量的名字,sig为这个函数和变量的签名信息。使用方法如下:

MyJni(JNIEnv *env, jobject mj)......

{

//先找到com.xxx.yyy.MyJni类在JNI层中对应的jclass实例。

jclass myJniInterface = env->FindClass("com.xxx.yyy.MyJni");

//取出MyJni类中函数jnitest的jMethodID。

mMyJniMethodID = env->GetMethodID(myJniInterface, "jnitest", "(Ljava/lang/String;JJ)V");

//取出MyJni类中函数jnitest1的jMethodID。

mJniTestMethodID = env->GetMethodID(myJniInterface, "jnitest1",

"(Ljava/lang/String;Ljava/lang/String;)V");

如果每次操作jobject前都去查询jmethodID或jfieldID,将会影响程序的运行效率,故在初始化时可取出ID并保存起来供后续使用。

使用jfieldID 和 jmethodID

实例代码如下:

virtual bool myjni(const char* path, long long lastModified, long long fileSize)

{

jstring pathstr;

if ((pathStr = mEnv->NewStringUTF(path)) == NULL)

return;

/*

调用JNIEnv的CallVoidMethod函数,注意CallVoidMethod的参数:

第一个是MyJni的jobject对象,

第二个是函数myjni的jmethodID,后面是Java中myjni的参数

*/

mEnv->CallVoidMethod(mClient, mMyJniMethodID, pathStr, lastModified, fileSize);

mEnv->DeleteLocalRef(pathStr);

return (!mEnv->ExceptionCheck());

通过JNIEnv输出CallVoidMethod,再把jobject、jMethodID和对应的参数传进去,JNI层就能调用Java对象的函数。

实际上JNIEnv输出一系列类似CallVoidMethod的函数,形式如下:

NativeType CallMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)

其中type对应Java函数的返回值类型,例如CallIntMethod、CallVoidMethod等。

上面是针对非static函数,如果调用Java的static函数,则用JNIEnv输出的CallStatic< Type>Method系列函数。

通过jfieldID操作jobject的成员变量,如下:

//获得filedID可调用GetField系列函数获取jobject对应的成员变量值

nativeType GetField(JNIEnv *env, jobject obj, jfieldID fieldID)

//或调用SetField系列函数设置jobject对应的成员变量值

void SetField(JNIEnv *env, jobject obj, jfield fieldID, NativeType value)

JNI类型签名介绍

static JNINativeMethod gMethods[] = {

......

{

"processFile"

"(Ljava/lang/String;Ljava/lang/String;Landroid/media/MyJni;)V",

(void*)com_xxx_yyy_MyJni

},

......

}

代码中字符串”(Ljava/lang/String;Ljava/lang/String;Landroid/media/MyJni;)V”是Java中对应函数的签名信息,有参数类型和返回值类型共同组成。Java支持函数重载,可定义同名但不同参数的函数,进根据函数名无法找到具体函数,故JNI技术中将参数类型和返回值类型作为函数的签名信息。

JNI规范定义的函数签名信息格式:

(参数1类型标示参数2类型标示...参数n类型标示)返回值类型标示

“(Ljava/lang/String;Ljava/lang/String;Landroid/media/MyJni;)V”,其中括号内是参数类型的标识,最右边是返回值类型的标识,void类型对应的标识是V。当参数的类型是引用类型时,其格式是“L包名;”,其中包名中的“.”换成“/”。Ljava/lang/String表示是一个Java的String类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442936.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 垃圾回收机制_Java的垃圾回收机制

前言在C语言中, 程序员必须小心谨慎的处理每一项内存分配, 且内存使用完后必须手动释放曾经占用的内存空间。当内存释放不够完全时, 即存在分配但永不释放的内存块, 就会引起"内存泄漏"问题。而在Java语言中, 它给了程序员一个美好的承诺: 程序员无需管理内存, 因为J…

java闹钟程序声音_跪求高手帮忙写一个JAVA手机闹钟程序 实现添加铃声和设置多闹钟...

展开全部import java.util.*;import java.awt.*;import java.applet.*;import java.text.*;public class AlarmClock extends Applet implements Runnable{Thread timernull; //创建线程timerImage clockp,gif1,gif2,clock6,clock7; //clockp:闹钟的外壳&#xff0c;闹铃和e68a…

摩托罗拉ex232java_摩托罗拉ex232r如何刷机?摩托罗拉ex232r评测

导语&#xff1a;随着 高科 技产业的发展&#xff0c;手机作为一个深受影响的产业&#xff0c;其竞争的激烈程度也是不言而喻的。市场好比战场&#xff0c;而为了在这个手机战场中赢 得胜 利&#xff0c;不论国内或者是国外的各大厂商也都全身心的投入到新技术的开发和新产品的…

JAVA捕捉输入格式异常_Java学习(四).异常处理

异常处理任何一个软件或程序都可能在运行的过程中出现故障&#xff0c;问题的关键是故障出现以后如何处理&#xff1f;谁来处理&#xff1f;怎样处理&#xff1f;处理后系统能否恢复正常的运行&#xff1f;本章在介绍Java处理这类问题基本方法的基础上&#xff0c;讨论包含异常…

php去除html属性,PHP如何去掉所有HTML标签?

PHP如何去掉所有HTML标签&#xff1f;在PHP中可以使用“strip_tags()”函数将字符串中的所有HTML标签去除&#xff0c;该函数用于从字符串中去除HTML和 PHP标记&#xff0c;其语法是“strip_tags(str)”&#xff0c;其参数str表示要进行操作的字符串&#xff0c;返回值为处理后…

php获取本机root,通过PHP执行root命令

慕村225694在尝试之前&#xff0c;请阅读整个文章&#xff0c;然后进行选择。使用二进制包装器(带有suid位)的解决方案1)创建一个脚本(最好是.sh)&#xff0c;其中包含要作为root用户运行的脚本。# cat > php_shell.sh < wrapper.c < #include #include int mai…

java寂静岭 攻略,GBA版《寂静岭》HARRY篇图文流程攻略

“Play Novel: Silent Hill”是KONAMI于2001年3月21日在GBA上推出的一款文字冒险游戏&#xff0c;剧情内容取自同社的恐怖冒险游戏——Silent Hill(《寂静岭》)。游戏基本上是纯粹的文字冒险游戏&#xff0c;过程中穿插着几段动画CG作为过场&#xff0c;游戏中绝大部分的图片和…

实验一熟悉matlab环境,数字信号处理报告实验一:熟悉MATLAB环境.doc

数字信号处理报告实验一&#xff1a;熟悉MATLAB环境.doc实验一熟悉MATLAB环境一 实验目的1. 熟悉MATLAB的主要操作命令。2. 学会简单的矩阵输入和数据读写。3. 掌握简单的绘图命令。4. 用MATLAB编程并学会创建函数。5. 观察离散系统的频率响应。二 实验内容2.用MATLAB实现下列序…

微擎cloud.mod.php,微擎“could not resolve ”、“could not resolve host”系列问题处理办法...

今天一个用户跟我说模块安装出现”could not resolve host:update.we10d.cn“报错&#xff0c;昨天在整理最近十个月用户搜索关键词排行的时候也发现”could not resolve host“、”could not resolve“还是占据不小的比例的。其实这类报错的处理方法大致相同&#xff0c;都是/…

php类如何变为静态调用,PHP类中静态方法如何调用非静态方法?_后端开发

php如何将字符串转成json_后端开发php将字符串转成json的方法是&#xff1a;可以通过json_encode()函数来实现。json_encode()函数用于对变量进行JSON编码&#xff0c;该函数如果执行成功&#xff0c;则返回JSON数据&#xff0c;反之则返回FALSE。PHP类中静态方法调用非静态方法…

PHP的注释标记是什么,html的注释标记是什么

html的注释标记是“”&#xff0c;用来在源文档中插入注释&#xff0c;注释的内容不会被显示在浏览器页面上。只有在文本编辑器中&#xff0c;或浏览器的“查看源代码”选项打开文档时&#xff0c;才能看到注释。本教程操作环境&#xff1a;windows7系统、HTML5版、Dell G3电脑…

linux 监控命令行输入,监控 Linux 容器性能的命令行神器

ctop是一个新的基于命令行的工具&#xff0c;它可用于在容器层级监控进程。容器通过利用控制器组(cgroup)的资源管理功能&#xff0c;提供了操作系统层级的虚拟化环境。该工具从cgroup收集与内存、CPU、块输入输出的相关数据&#xff0c;以及拥有者、开机时间等元数据&#xff…

linux子系统停止运行,linux 系统部署spring boot 退出连接端后项目停止运行问题

准备&#xff1a;Linux系统、jar包、一个启动项目文件(starup.sh)文件名自定义1、首先需要编辑starup.sh文件&#xff0c;这里我也是从网上找了一个比较好的内容如下&#xff1a;#!/bin/bash#这里可替换为你自己的执行程序&#xff0c;其他代码无需更改APP_NAMEkaRen.jar#使用说…

linux程序mktime无权限,linux中mktime算法解析

Linux源码中的mktime算法解析我们知道&#xff0c;从CMOS中读出来的系统时间并不是time_t类型&#xff0c;而是类似于struct tm那样&#xff0c;年月日时分秒是分开存储的。那么&#xff0c;要把它转化为系统便于处理的time_t类型&#xff0c;就需要算法进行转换。我们都知道我…

linux 无线网卡连接网络连接不上去,【已解决】Ubuntu 10.04 无线网卡 无法连接

----------------------------------搬家声明------------------------------------------------------------------------搬家声明--------------------------------------【已解决】Ubuntu 10.04 无线网卡 无法连接【问题】新装的Ubuntu 10.04&#xff0c;其他一切正常&#…

Linux 软件包管理器的目的是什么,Linux软件包的管理--RPM包管理器

在Linux中如何安装、升级、卸载软件&#xff0c;是我们日常运维中重要的组成部分。接下来一CentOS6系统为例&#xff0c;讲解如何使用 RPM 包管理器&#xff0c;yum包管理器以及源码的方式来管理我们的软件包。一、相关的背景知识许多程序的源程序&#xff0c;例如使用C语言编写…

嵌入式linux mongodb,小白在Ubuntu安装mongoDB与mongo-c-driver

目的&#xff1a;本人从事嵌入式软件&#xff0c;项目中需要使用MongoDB&#xff0c;最终需要熟悉c-driver的API&#xff0c;小白在搭建环境有些浪费时间&#xff0c;故写这文章让与我同样状态的开发人员学习学习。在Ubuntu上的安装mongodb方法一&#xff1a;sudo apt-get ins…

湘潭大学-软件工程-选择判断题复习

说明 期末考试单选题和判断题占30分&#xff0c;单选20&#xff0c;判断10分 单选题 选错误的 B依靠松散组合的互联网大众是无法开发出高质量软件产品的 D、所有命名都应尽量使用缩写 C、采用团队的组织方式 D、软件需求一旦确定就不允许变化 以下哪一项是通过运行程序…

c语言运算符ppt,C语言知识学习运算符.ppt

C语言知识学习运算符.ppt 第三章,C语言运算符,回顾,变量和常量的含义 熟悉基本数据类型 - int、char、float 和 double 使用算术运算符 理解类型转换 熟练使用 scanf 和 printf 函数,课程目标,算术运算符 增量运算符 逻辑运算符 关系运算符 按位运算符 C的特殊运算符 --“” “…

ionic判断android版本,$ionicplatform 判断是android还是ios?

一只名叫tom的猫安装环境首先应该安装好 node.js (略)&#xff0c;然后安装cordova、ionic等sudo npm install -g cordova ionic ios-sim创建不同类型的项目目前可以用blank&#xff0c;tabs&#xff0c;sidemenu三种ionic start myApp tabs常用插件cordova plugin add com.ion…