JNI中调用Java函数

在这里插入图片描述


文章目录

  • 一、JNI 注册
  • 二、JNI 调用 Java 函数
    • 1、实例
    • 2、总结
    • 3、参考
  • 三、JNI 数据传递
  • 四、JNA
  • 五、图像传递


一、JNI 注册

    JNI 分成静态注册和动态注册

  1. 静态注册

    cpp 实现

JNIEXPORT jstring JNICALL
Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv *env, jobject thiz) {// ...
}

    Java 中使用

package com.example.hellojni
class HelloJni : AppCompatActivity() {// ...override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// ...binding.helloTextview.text = stringFromJNI()}external fun stringFromJNI(): String?companion object {init {System.loadLibrary("hello-jni")}}
}
  1. 动态注册
// 动态注册
namespace android {static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length) {// ...}
}static const JNINativeMethod methods[] = {{"native_open",  "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_MemoryFile_open},{"native_mmap",  "(Ljava/io/FileDescriptor;II)I", (void*)android_os_MemoryFile_mmap},{"native_munmap", "(II)V", (void*)android_os_MemoryFile_munmap},{"native_close", "(Ljava/io/FileDescriptor;)V", (void*)android_os_MemoryFile_close},{"native_read",  "(Ljava/io/FileDescriptor;I[BIIIZ)I", (void*)android_os_MemoryFile_read},{"native_write", "(Ljava/io/FileDescriptor;I[BIIIZ)V", (void*)android_os_MemoryFile_write},{"native_pin",   "(Ljava/io/FileDescriptor;Z)V", (void*)android_os_MemoryFile_pin},{"native_get_size", "(Ljava/io/FileDescriptor;)I",(void*)android_os_MemoryFile_get_size}
};int AndroidRuntime::registerNativeMethods(JNIEnv* env,const char* className, const JNINativeMethod* gMethods, int numMethods)

5分钟理解Android中的JNI原理

二、JNI 调用 Java 函数

    JNI 调用 Java 函数,主要是在 JNI 中使用反射调用 Java 中的函数。

1、实例

  1. Java代码:
package com.my.hawk.jni2;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import static java.lang.String.format;public class MainActivity extends AppCompatActivity {TextView tv;// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// Example of a call to a native methodtv = findViewById(R.id.sample_text);tv.setText(stringFromJNI());nativeInitilize();Button startBt = findViewById(R.id.button);startBt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {nativeThreadStart();}});Button stopBt = findViewById(R.id.button2);stopBt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {nativeThreadStop();}});}public void onNativeCb(int count) {Log.d("Native", "onNativeCb count=" + count);
//        TextView tv = findViewById(R.id.sample_text);
//        tv.setText(format("%s%d", stringFromJNI(), count));tv.post(new Runnable() {@Overridepublic void run() {tv.setText(format("%s%d", stringFromJNI(), count));}});}/*** A native method that is implemented by the 'native-lib' native library,* which is packaged with this application.*/public native String stringFromJNI();public native void nativeInitilize();public native void nativeThreadStart();public native void nativeThreadStop();
}
  1. JNI代码
#include <jni.h>
#include <string>
#include <sstream>
#include <android/log.h>
#include <unistd.h>JavaVM *gJavaVm;
jobject gJaveObj;
static volatile int gIsThreadExit = 0;#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "Native", __VA_ARGS__)static const char *classPath = "com/my/hawk/jni2/MainActivity";extern "C" JNIEXPORT jstring JNICALL
Java_com_my_hawk_jni2_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_my_hawk_jni2_MainActivity_nativeInitilize(JNIEnv *env, jobject thiz) {env->GetJavaVM(&gJavaVm);gJaveObj = env->NewGlobalRef(thiz);
}static void* native_thread_exec(void *arg) {JNIEnv *env;gJavaVm->AttachCurrentThread(&env, nullptr);//    jclass javaClass = env->FindClass(classPath);jclass javaClass = env->GetObjectClass(gJaveObj);if (javaClass == nullptr) {LOG("Fail to find javaClass");return nullptr;}jmethodID javaCallback = env->GetMethodID(javaClass, "onNativeCb", "(I)V");if (javaCallback == nullptr) {LOG("Fail to find method onNativeCb");return nullptr;}LOG("native_thread_exec loop enter");int count = 0;while (!gIsThreadExit) {env->CallVoidMethod(gJaveObj, javaCallback, count++);sleep(1);}gJavaVm->DestroyJavaVM();LOG("native_thread_exec loop leave");return nullptr;
}extern "C"
JNIEXPORT void JNICALL
Java_com_my_hawk_jni2_MainActivity_nativeThreadStart(JNIEnv *env, jobject thiz) {gIsThreadExit = 0;pthread_t threadId;if (pthread_create(&threadId, nullptr, native_thread_exec, nullptr) != 0) {LOG("native_thread_start pthread_create fail!");return;}LOG("native_thread_start success");
}extern "C"
JNIEXPORT void JNICALL
Java_com_my_hawk_jni2_MainActivity_nativeThreadStop(JNIEnv *env, jobject thiz) {gIsThreadExit = 1;LOG("native_thread_stop success");
}

    其中的关键,获取方法,然后通过反射调用 native_thread_exec,初始化的时候保存全局 JVMclass 对象。

    env->GetJavaVM(&gJavaVm);gJaveObj = env->NewGlobalRef(thiz);

2、总结

  1. Android 环境中,每个进程只能诞生一个 JavaVM 对象,被所有线程共享。在 VM 加载 *.so 程序库时,会先调用 JNI_OnLoad() 函数,在 JNI_OnLoad() 函数中会将 JavaVM 指针对象保存到 CJNI 的全局变量中。
  2. JNIEnv 对象和线程是一一对应的关系;
  3. JvmJNIEnv 释放问题?JVMJava Heap 的内存泄漏?JVM 内存中 native memory 的内存泄漏?
  4. 从操作系统角度看,JVM 在运行时和其它进程没有本质区别。在系统级别上,它们具有同样的调度机制,同样的内存分配方式,同样的内存格局。JVM 进程空间中,Java Heap 以外的内存空间称为 JVM 的 native memory。进程的很多资源都是存储在 JVM 的 native memory 中,例如载入的代码映像,线程的堆栈,线程的管理控制块,JVM 的静态数据、全局数据等等。也包括 JNI 程序中 native code 分配到的资源。
    Local Reference 导致的内存泄漏?

3、参考

Android开发实践:JNI层线程回调Java函数示例 - 指针空间 - 博客园

JNI开发:JNI层新起的函数中(C回调函数中)调用JAVA层的接口_tingzhushaohua的博客-CSDN博客_jni 回调函数

C++通过JNI层回调java函数 - 百度文库

Android NDK开发(一) - 简书

jni java 函数指针_java native interface JNI 调用Java方法_我是XiaoYang呀的博客-CSDN博客

三、JNI 数据传递

Android:JNI调用C++自定义类的详细方法_chaoqiangscu的博客-CSDN博客_jni调用c++类

Java代码与Jni层之间传递数组(byte[])_xiao慕r的博客-CSDN博客_jni传递数组

Android-JNI之数据类型转换_zhezi521的博客-CSDN博客_android jni 类型转换

android ndk 返回字符串,android ndk返回String(字符串)_天才娜娜ln的博客-CSDN博客

小心ReleaseByteArrayElements 中的参数问题_普通网友的博客-CSDN博客

JNIEnv*的常用函数详解

java jni 手册_Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释_发条粽子的博客-CSDN博客

NDK 开发之 Bitmap 的使用-技术圈

Android之OpenCv简单人脸识别功能(Bitmap)_路和远方的博客-CSDN博客_android opencv 人脸识别

JNI层向Java层传递bitmap | 码农家园

android中通过JNI读取Bitmap文件,并调用opencv进行处理_一天到晚游泳的鱼啊鱼的博客-CSDN博客

JNI String类型 - 知乎

JNI 通过形参String返回数据的方法_Cosmo_Wang1989的博客-CSDN博客_jni 形参返回字符串

简介Bitmap、YUV,NV21与Bitmap互转_XDK-Net的博客-CSDN博客_bitmap转nv21

bitmap 转换nv21_驱梦人的博客-CSDN博客_bitmap转nv21

JNI层向Java层传递bitmap | 码农家园

计算Java函数的签名 |

Android开发实践:JNI函数签名生成器 - 行业资讯 - 肥雀云_南京肥雀信息技术有限公司


native和static native区别_飞鸟_的博客-CSDN博客_jni static

四、JNA

JNI便捷开发框架JNA框架之入门(一)_cy谭的博客-CSDN博客_jna

JNI便捷开发框架JNA框架之指针参数Pointer(二)_cy谭的博客-CSDN博客_jna pointer

JNI便捷开发框架JNA框架之引用传递ByReference(三)_cy谭的博客-CSDN博客

JNI便捷开发框架JNA框架之结构参数体传递(四)_cy谭的博客-CSDN博客_jna 结构体传参

JNA传递二维指针数组参数给C语言_Xeon_CC的博客-CSDN博客_jna传递数组给c

JNA 技术解密_ccfeng2008的博客-CSDN博客_jna原理

jna编程学习 - 走看看

JNA 使用 回调函数 - 博麗靈夢 - 博客园

java高级用法之:JNA中的回调_flydean程序那些事的博客-CSDN博客_jna 回调函数

Jna及如何调试_nanshenjiang的博客-CSDN博客_jna测试

libffi浅析_ayu_ag的博客-CSDN博客_libffi

使用 libffi 实现 AOP_diaoju3333的博客-CSDN博客

【libffi】动态调用&定义C函数_Yaso_GG的博客-CSDN博客_libffi

深入浅出JNA

android下使用JNA_10km的博客-CSDN博客_android jna

Ubuntu 12.04下制作JNA For Android_齐北的博客-CSDN博客

五、图像传递

移动端视频进阶(三):OpenCV的集成及视频帧转cv::Mat的相关操作_木大白易的博客-CSDN博客

Android 相机 NV21 byte[] 和 JPEG byte[] 转 OpenCV 的 Mat_weixin_33973609的博客-CSDN博客

在IOS上YUV NV21格式的CVPixelBufferRef转opencv的RGB格式cv::Mat的方法_星辰辰大海的博客-CSDN博客

   

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

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

相关文章

【深蓝学院】手写VIO第7章--VINS初始化和VIO系统--笔记

0. 内容 1. VIO回顾 整个视觉前端pipeline回顾&#xff1a; 两帧图像&#xff0c;可提取特征点&#xff0c;特征匹配&#xff08;描述子暴力匹配或者光流&#xff09;已知特征点匹配关系&#xff0c;利用几何约束计算relative pose([R|t])&#xff0c;translation只有方向&…

Linux Centos7 下使用yum安装的nginx平滑升级

1. 查看当前nginx版本 1nginx -v2. 查看centos版本 1cat /etc/redhat-release3. 创建一个新的文件nginx.repo&#xff0c;其中第三行的7是因为我的centos版本是7点多的&#xff0c;你看自己是多少就改多少 1vim /etc/yum.repos.d/nginx.repo23[nginx]4namenginx repo 5baseu…

2023年中国超导磁体市场规模、需求量及行业竞争现状分析[图]

超导磁体一般是指用超导导线绕制的能产生强磁场的超导线圈&#xff0c;还包括其运行所必要的低温恒温容器。通常电磁铁是利用在导体中通过电流产生磁场&#xff0c;由于超导材料在超导状态下具有零电阻特性&#xff0c;因此可以以极小的面积通过巨大的电流。超导磁体具有场强高…

如何自制一本电子书,安利一个平台

有没有想过把纸质版的书刊制作成图文相结合的电子书&#xff0c;实现随时随地的阅读。其实很多人在实际制作时常常陷入困扰&#xff1a;创意不够&#xff0c;无法找到理想的素材&#xff0c;制作繁琐等等。感觉好难啊&#xff01; 不过&#xff0c;幸运的是&#xff0c;我发现…

补环境框架

GitHub - bnmgh1/node-sandbox: 魔改Node补环境框架 GitHub - fanchangrui/catvm: js逆向环境框架基础&#xff08;持续补充&#xff09;&#xff08;沙盒框架&#xff09;

201、RabbitMQ 之 Exchange 典型应用模型 之 工作队列(Work Queue)

目录 ★ 工作队列介绍代码演示测试注意点1&#xff1a;注意点2&#xff1a; ★ 工作队列介绍 工作队列&#xff1a; 就是让多个消费者竞争消费同一个消息队列的消息&#xff0c;相当于多个消费者共享消息队列。 ▲ RabbitMQ可以让多个消费者竞争消费同一个消息队列 ▲ 消息队…

thinkphp6 - 超详细使用阿里云短信服务发送验证码功能,TP框架调用对接阿里云短信发验证码(详细示例代码,一键复制开箱即用)

效果图 在thinkphp 5/6 框架(只要不是太低的版本就能用)中,实现接入调用阿里云短信服务详细教程,整个配置过程及示例代码保证小白也能轻松完成! 直接复制就行,改个阿里云参数就能用了。

了解三层架构:表示层、业务逻辑层、数据访问层

目录 背景&#xff1a; 三层架构 什么是三层: 分层的目的&#xff1a; 三层的结构关系​编辑 三层表现形式:​编辑 三层的优缺点&#xff1a; 总结: 背景&#xff1a; 三层架构是一种软件设计模式&#xff0c;可称为客户端-服务器-架构&#xff0c;把各个功能模块划分…

MySql运维篇---009:分库分表:垂直拆分、水平拆分、通过MyCat进行分片,读写分离:一主一从、 双主双从

3.分库分表 3.1 介绍 3.1.1 问题分析 使用单个数据库存储所有的数据&#xff0c;如果磁盘和内存和内存不足了可以增大磁盘和内存&#xff0c;但是对于一台服务器的磁盘和内存不可能无限制的扩张下去&#xff0c;它是受我们服务器的硬件影响的&#xff0c;如果说数据库所存储…

C语言字符串查找函数和错误信息报告函数(strstr、strtok,strerror)

文章目录 摘要1 strstr1.1 函数使用1.2 模拟实现 2. strtok2.1 函数介绍 3. strerror3.1 函数介绍3.2 strerror 与 perror 摘要 本篇文章介绍了C语言中常用的字符串处理函数&#xff0c;包括字符串查找函数 strstr 和字符串分割函数 strtok&#xff0c;以及错误信息报告函数 s…

Linux知识点 -- 网络基础 -- 数据链路层

Linux知识点 – 网络基础 – 数据链路层 文章目录 Linux知识点 -- 网络基础 -- 数据链路层一、数据链路层1.以太网2.以太网帧格式3.重谈局域网原理4.MAC地址5.MTU6.查看硬件地址和MTU的命令7.ARP协议 二、其他重要协议或技术1.DNS&#xff08;Domain Name System&#xff09;2.…

三相空气开关

一、三相空开的作用 三相空气开关对任意一相出现过载或短路&#xff0c;均起到保护作用。 二、三相空气开关原理图&#xff1a; 1、老式空气开关 1)、短路时&#xff0c;电磁脱钩器工作 2)、过载时&#xff0c;发热元件引起双金属片弯曲&#xff0c;使脱钩器工作 3)、测试按…

RabbitMQ开启消息跟踪日志(trace)

Trace 是Rabbitmq用于记录每一次发送的消息&#xff0c;方便使用Rabbitmq的开发者调试、排错。 1、启动Tracing插件 在RabbitMQ中默认是关闭的&#xff0c;需手动开启。此处rabbitMQ是使用docker部署的 ## 进入rabbitMq中 docker exec -it rabbitmq1 bash ## 启动日志插件 r…

别再使用循环的方式筛选元素了!开发常用的Stream流+Lambda表达式过滤元素了解过吗?10000字超详细解析

目录 1. Stream 流的简单展示 1.1 抛出问题 1.2 传统解决问题的编码方式 1.3 Stream 流的方式过滤元素 2. Stream 流的核心思想 3. Stream 流的使用 3.1 获取 stream 流 3.1.1 单列集合获取 stream 流 3.1.2 双列集合获取 stream 流 3.1.3 数组获取 stream 流 3.1.4…

低功耗蓝牙(BLE)开发——Qt

背景知识 低功耗蓝牙比经典蓝牙复杂些&#xff0c;需要了解一些协议的基础知识。 此部分参考博客GATT Profile 简介-CSDN博客 GATT详细介绍-CSDN博客 Introduction | Introduction to Bluetooth Low Energy | Adafruit Learning System 蓝牙 (四) GATT profile-CSDN博客 关…

Centos中利用自带的定时器Crontab_实现mysql数据库自动备份_linux中mysql自动备份脚本---Linux运维工作笔记056

这个经常需要,怕出问题因而需要经常备份数据库,可以利用centos自带的定时器,配合脚本实现自动备份. 1.首先查看一下,这个crontab服务有没有打开: 执行:ntsysv 可以看到已经开机自启动了. 注意这个操作界面,用鼠标不行,需要用,tab按键,直接tab到确定,或取消,然后按回车回到命…

CSS 之 table 表格布局

一、简介 ​ 除了使用HTML的<table>元素外&#xff0c;我们还可以通过display: table/inline-table; 设置元素内部的布局类型为表格布局。并结合table-cell、table-row等相关CSS属性值可以实现HTML中<table>系列元素的效果&#xff0c;具有表头、表尾、行、单元格…

Docker-compos

Docker-compose 简介 Docker-Compose项目是基于Python开发的Docker官方开源项目&#xff0c;负责实现对Docker容器集群的快速编排。 Docker-Compose将所管理的容器分为三层&#xff0c;分别是 工程&#xff08;project&#xff09;&#xff0c;服务&#xff08;service&#…

HSRP热备份路由器协议的解析和配置

HSRP的解析 个人简介 HSRP hot standby router protocol 热备份路由协议&#xff08;思科私有协议&#xff09; HSRP v1 version 1 HSRP v2 version 2 虚拟一个HSRP虚拟IP地址 192.168.1.1 开启HSRP的抢占功能 通过其他参数 人为调整谁是主 谁是从 &#xff01; 查…

记录一次线上fullgc问题排查过程

某天&#xff0c;接到测试部门反馈说线上项目突然很快&#xff0c;由于当前版本代码和上一版本相比就多了一个刚上线了一个5分钟1次的跑批任务&#xff0c;先关闭次任务后观察是否卡顿&#xff0c;并检查堆内存是否使用完造成频繁gc 1.通过jmap命令查看堆内存中的对象 2.生成当…