JNI中调用Java函数

news2024/11/17 10:44:01

在这里插入图片描述


文章目录

  • 一、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");
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // Example of a call to a native method
        tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
 
        nativeInitilize();
 
        Button startBt = findViewById(R.id.button);
        startBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                nativeThreadStart();
            }
        });
 
        Button stopBt = findViewById(R.id.button2);
        stopBt.setOnClickListener(new View.OnClickListener() {
            @Override
            public 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() {
            @Override
            public 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.coloradmin.cn/o/1084049.html

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

相关文章

【TensorFlow2 之012】TF2.0 中的 TF 迁移学习

#012 TensorFlow 2.0 中的 TF 迁移学习 一、说明 在这篇文章中&#xff0c;我们将展示如何在不从头开始构建计算机视觉模型的情况下构建它。迁移学习背后的想法是&#xff0c;在大型数据集上训练的神经网络可以将其知识应用于以前从未见过的数据集。也就是说&#xff0c;为什么…

omnipathr官网教程 mistr

github python版本 omnipath tutorials Issue #17 saezlab/omnipath (github.com) R版本 saezlab/OmnipathR: R client for the OmniPath web service (github.com)https://github.com/saezlab/OmnipathR GitHub - saezlab/OmnipathR: R client for the OmniPath web s…

Prettier插件使用

一、前言 由于之前使用的Beautify格式化插件已经没有在维护了&#xff0c;所以这里再分享一个Formatter插件-Prettier。 二、插件安装 首先在扩展(ctrlShiftX)中搜索关键词Prettier&#xff0c;点击安装。 三、插件使用配置 首先在VSCode编辑器中依次打开菜单文件-首选项-…

Oauth2.0单点登录的解决方案 安当加密

上海安当技术有限公司的ASP身份认证系统提供针对Oauth2.0单点登录的解决方案。该解决方案可以帮助客户实现以下目标&#xff1a; 统一的用户管理&#xff1a;Oauth2.0单点登录可以提供一个统一的用户管理平台&#xff0c;使得用户只需要在一个平台上进行注册和身份认证&#x…

基于Java使用SpringBoot+Vue框架实现的前后端分离的美食分享平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 在当今社会&#xff0…

打造类ChatGPT服务,本地部署大语言模型(LLM),如何远程访问?

ChatGPT的成功&#xff0c;让越来越多的人开始关注大语言模型&#xff08;LLM&#xff09;。如果拥有了属于自己的大语言模型&#xff0c;就可以对其进行一些专属优化。例如&#xff1a;打造属于自己的AI助理&#xff0c;或是满足企业自身的业务及信息安全需求。 所以&#xff…

天猫商品评论数据接口,天猫商品评论API接口,天猫API接口

天猫商品评论内容数据接口的步骤&#xff0c;但是可以提供淘宝商品评论内容数据接口的步骤&#xff1a; 授权获得淘宝开放平台API所需的权限。获取AppKey和AppSecret等认证信息。发送HTTP请求&#xff0c;获取所需评价信息。对获取到的评价信息进行处理和解析。结果处理&#…

行业顶流|AI数字人直播,低成本、高回报的新趋势

去年&#xff0c;元宇宙的概念炒得特别火&#xff0c;落地却寥寥无几&#xff0c;今年的AI数字人是否也只是一时炒作的概念呢&#xff1f; 在这个信息时代&#xff0c;科技的发展总是伴随着各种概念的冒起。元宇宙作为其中之一&#xff0c;的确在一瞬间扑面而来&#xff0c;引…

《机器学习》第5章 神经网络

文章目录 5.1 神经元模型5.2 感知机与多层网络5.3 误差逆传播算法5.4 全局最小与局部最小5.5 其他常见神经网络RBF网络ART网络SOM网络级联相关网络Elman网络Boltzmann机 5.6 深度学习 5.1 神经元模型 神经网络是由具有适应性的简单单元组成的广泛并行互连的网络&#xff0c;它…

数字化转型,河北吉力宝—传统行业的自我救赎新标杆

近年来,国家出台了各项政策支持企业数字化转型,“十四五”计划更是将建设数字经济作为重要发展目标,中国人工智能产业进入爆发式增长阶段,市场潜力巨大。随着数字化时代的到来&#xff0c;加快发展数字经济成为把握新一轮科技革命和产业变革新机遇的战略选择。 健康卫生事件后…

React如何优化减少组件间的重新Render

目前写了不少React的项目&#xff0c;发现React有些特点更灵活和注重细节&#xff0c;很多东西需要有一定的内功才能掌握好&#xff1b;比如在项目中常常遇到的组件重复渲染&#xff0c;有时候组件重复渲染如果内容是纯文本&#xff0c;不打印日志就不容易发现重复渲染了&#…

Maven - 5 分钟快速通关

目录 一、Maven 1.1、 基础语法 1.2、聚合 1.3、继承 1.4、自定义属性 一、Maven 1.1、 基础语法 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/…

RN(React Native)的应用程序在雷电模拟器可以运行,安卓真机运行失败问题解决记录

yarn react-native build-android打包的apk在真机安卓运行提示&#xff1a; Unable to load script . Make sure you re either running Metro ( run npx react - native start ) or that your bundle index . android . bundle is packaged correctly for release . jn…

基于JavaWeb+SpringBoot+Vue超市管理系统的设计和实现

基于JavaWebSpringBootVue超市管理系统的设计和实现 源码传送入口前言主要技术系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码传送入口 前言 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发…

适合学生写作业的台灯有哪些?高品质学生读写台灯推荐

不得不说如今我国青少年儿童的近视率还是非常高的&#xff0c;据国家卫健委疾控局数据&#xff0c;我国儿童青少年总体近视率为52.7%&#xff0c;其中6岁儿童为14.3%&#xff0c;小学生为35.6%&#xff0c;初中生为71.1%&#xff0c;高中生为80.5%&#xff0c;造成近视的原因不…

PLC编程速成(二)

目录 操作符 什么是操作符&#xff1f; 变量表&#xff08;数据类型&#xff09; 常用的类型&#xff1a; 变量表图 设置复位指令 如何重复双线圈与解决复双线圈问题&#xff1f; 解决复双线圈 ​编辑 重复双线圈 置复位指令&#xff08;有置位就存在复位&#xff09;…

声量暴涨130%,小红书「待爆」赛道创作指南

近年来&#xff0c;小红书影视板块展现出了旺盛的生命力。热门赛道逼近饱和的当下&#xff0c;内容如何不断推陈出新&#xff0c;成为营销困局。 本期&#xff0c;千瓜将锁定蓄势待发的影视板块&#xff0c;梳理“影视”内容打造方式&#xff0c;助力品牌开疆扩土&#xff0c;抢…

【图像误差测量】测量 2 张图像之间的差异,并测量图像质量(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

离散数学 学习 之 递推方程和生成函数

递推方程 注意这里的特征根一定不是相等 特解的话一般要去设出基本的形式 这是0 次多项式 生成函数

Kepler.gl笔记:地图交互

1 双图 点第一个图标&#xff0c;进入双图 双图可以选择各自显示哪些layer 2 2D图转3D图 点击第二个图标 鼠标拖拽是控制位置 ctrl鼠标拖拽是旋转 3 显示图例