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只有方向&…

EsayExcel让不同标题有不同的颜色

今天我在github社区的时候遇见了这个issues&#xff0c;我有看了下百度发现很多人需要这个问题的解决方案&#xff0c;接下来我就写一份这个问题的解决方案。 您的需求&#xff1a; ​ 您好我了解到您的需求&#xff0c;您的需求是为每一个标题设置不同的颜色。 我的解决方案…

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…

Unity后台登录/获取数据——BestHTTP的使用Get/Post

一、使用BestHTTP实现登录功能&#xff08;Post&#xff09; 登录具体的步骤如下&#xff1a; 1&#xff1a;传入你的用户名和密码&#xff0c;这是一条包括链接和用户名密码的链接 2&#xff1a;使用BestHTTP的Post功能将链接传到服务器后台 3&#xff1a;后台拿到了你传送…

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

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

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

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

【Method】把 arXiv论文 转换为 HTML5 网页

文章目录 MethodReference https://ar5iv.labs.arxiv.org/ Articles from arXiv.org as responsive HTML5 web pages. 可以将来自 arXiv 的 PDF 论文渲染成 HTML5 网页版本。 Method View any arXiv article URL by changing the X to a 5. 将 arXiv 网址中的 x 换成 5 再回…

教程分享:如何将微信公众号变成淘宝客查券返利机器人自动赚佣金?

教程分享&#xff1a;如何将微信公众号变成淘宝客查券返利机器人自动赚佣金&#xff1f; 在现代社交媒体和电商激烈的竞争中&#xff0c;有一种强大的工具可以帮助你在微信公众号上轻松实现查券和返利功能&#xff0c;而且全自动赚取佣金。这个工具就是"微赚淘客系统3.0&…

补环境框架

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 框架(只要不是太低的版本就能用)中,实现接入调用阿里云短信服务详细教程,整个配置过程及示例代码保证小白也能轻松完成! 直接复制就行,改个阿里云参数就能用了。

2023-10-11

昨晚有点事&#xff0c;把日记忘了&#xff0c;今天补一下捏。 昨天回本部办了一些事情&#xff0c;一直搞到了晚上&#xff0c;所以基本啥也没干.... 然后实验太多了&#xff0c;得抓紧把实验报告给写了

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

目录 背景&#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…

SpringBoot使用随机端口启动

1.获取可用端口工具类 import java.net.InetAddress; import java.net.Socket; import java.util.Random;public class ServerPortUtil {private static final int MAX_PORT 65535;private static final int MIN_PORT 8000;public static String getAvailablePort() {Random…

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

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

gunicorn

gunicorn 是一个 Python WSGI HTTP 服务器 可以用于运行 Python 网站或 Web 应用程序。 WSGI&#xff08;Web Server Gateway Interface&#xff09;定义了一种标准的接口&#xff0c; 将 Web 服务器和 Python 应用程序分离开来&#xff0c;使得 Web 服务器可以与不同的 Pytho…

[Machine learning][Part4] 线性回归模型技巧

目录 正规方程法 梯度下降法 缩放特征 学习率选择 正规方程法 这种方法可以不多次迭代梯度下降函数就能得到w,b。但是缺点是在大量数据训练情况下效率较低&#xff0c;其次是这种算法仅仅在线性回归中实现了&#xff0c;并没有在其他模型中实现&#xff0c;因此&#xff0c…

小程序A跳转小程序B并且自动登录

需求 例如有一个小程序A&#xff0c;A中有一个功能需要跳转小程序B进行查看。需要点击此功能跳转至小程序B,并且自动登录 实现方式 小程序A的跳转方法 wx.navigateToMiniProgram({appId: "目标小程序APPID",path: "目标小程序小程序页面",extraData: {use…