码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 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) {
    	// ...
    }
    
    • 1
    • 2
    • 3
    • 4

        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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    1. JNI代码
    #include 
    #include 
    #include 
    #include 
    #include 
     
    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");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

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

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

    2、总结

    1. Android 环境中,每个进程只能诞生一个 JavaVM 对象,被所有线程共享。在 VM 加载 *.so 程序库时,会先调用 JNI_OnLoad() 函数,在 JNI_OnLoad() 函数中会将 JavaVM 指针对象保存到 C 层 JNI 的全局变量中。
    2. JNIEnv 对象和线程是一一对应的关系;
    3. Jvm 和 JNIEnv 释放问题?JVM 中 Java 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博客

       

  • 相关阅读:
    CSS3 2D转换-扭曲、缩放
    基于SSM+Vue的网络教学平台的设计与实现的设计与实现
    PUK码怎么解锁
    训练集表达的分类规则整理
    一元二次函数教案
    斜颈的分类有多少种?
    Java中的枚举是什么?
    【教学类-16-01】20221122《世界杯七巧板A4-随机参考图》(大班)
    记录前端通过XShell和xftp发布版本
    (转)富文本编辑器——Vue2Editor
  • 原文地址:https://blog.csdn.net/Liuqz2009/article/details/133785329
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号