• java调用jni全流程,简洁易懂!


    博主的测试环境为:
    mac os
    其他操作系统其实差不多

    步骤一

    编写一个java类:

    package com.test;
    
    public class MyNative {
        public static void main(String[] args) {
            System.out.println(func_int());
        }
        static{
                /**
                 这里填写动态库的全路径即可
                mac环境使用mynative.jnilib
                linux环境使用mynative.so
                windows环境使用mynative.dll
                **/
                System.load("/Users/mynative.jnilib");
        }
        public static native int func_int();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    步骤二

    1. 将上述java文件编译为MyNative.class文件
    2. 打开命令行cd到MyNative.class所在的文件夹
    3. 然后执行命令
    javah -jni -encoding utf-8 com.test.MyNative
    
    • 1
    1. 然后就能获得头文件"com_test_MyNative.h"
    2. 在当前文件夹新建一个cpp文件,命名随意,假设命名为"com_test_MyNative.cpp"

    经过一番操作后,如无意外,你会获得类似下图文件:
    在这里插入图片描述

    步骤三

    正式开撸C++代码

    #include "com_test_MyNative.h"
    JNIEXPORT jint JNICALL Java_com_test_MyNative_1func_1int(JNIEnv *env, jobject)
    {
        jint a = 111;
        return a;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    为简洁教学,就简单几句代码

    步骤四

    编译C++
    执行下面命令

    g++ 
    -I "/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/include" 
    -I "/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/include/darwin" 
    -shared 
    -o mynative.jnilib com_test_MyNative.cpp
    
    • 1
    • 2
    • 3
    • 4
    • 5

    命令解释
    -o 不解释
    -I 参数是用来指定头文件所在目录,不加上的话,会报错找不到’jni.h’ file not found
    -shared 表示编译为动态库,不加上的,否则会报错如下

    Undefined symbols for architecture x86_64:
    “_main”, referenced from:
    implicit entry/start for main executable
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    到此,如无意外,你的文件将会类似如下图
    在这里插入图片描述

    步骤五

    直接运行MyNative.java文件,如无意外,会打印出"111"

    OK! java调用jni教程至此结束!接下来开始C++调用java

    步骤一

    修改MyNative.java,添加一个静态java方法,以待C++调用

    package com.test;
    
    public class MyNative {
        public static void main(String[] args) {
            System.out.println(func_int());
        }
        static{
                /**
                 这里填写动态库的全路径即可
                mac环境使用mynative.jnilib
                linux环境使用mynative.so
                windows环境使用mynative.dll
                **/
                System.load("/Users/mynative.jnilib");
        }
        public static native int func_int();
        
        // 添加一个静态方法
        public static String bigunOK(String ss){
            System.out.println("C++调用java:"+ss);
            return "ok"+ss;
        };}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    步骤二

    在c++中调用上述的bigunOK方法

    #include "com_test_MyNative.h"
    jclass cls;			// 注意!这里必须要用全局变量,否则运行失败
    jmethodID mid;	 // 注意!这里必须要用全局变量,否则运行失败
    
    JNIEXPORT jint JNICALL Java_com_test_MyNative_1func_1int(JNIEnv *env, jobject)
    {
        // c++调用java --- start
        cls = (env)->FindClass("com/bigun/packtool/PackNative");
        if (cls != 0)
        {
            // 获取方法ID, 通过方法名和签名, 调用静态方法
            mid = (env)->GetStaticMethodID(cls, "bigunOK", "(Ljava/lang/String;)Ljava/lang/String;");
            // 此外,如果静态方法是没有参数的,那么填 "()V",如(env)->GetStaticMethodID(cls, "bigunOK", "()V");
        }
        if (mid != 0)
        {
            const char *name = "World";
            jstring arg = (env)->NewStringUTF(name);
            jstring result = (jstring)(env)->CallStaticObjectMethod(cls, mid, arg);
            const char *str = (env)->GetStringUTFChars(result, 0);
            printf("Result of sayHello: %s\n", str);
            (env)->ReleaseStringUTFChars(result, 0);
        }
        // c++调用java --- end
        
        jint a = 111;
        return a;
    }
    
    • 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

    OK~!重新编译一下,然后运行java代码,如无意外,则输入如下图所示:
    在这里插入图片描述
    恭喜你!成功啦~!

    OK! C++调用java也就此结束啦

  • 相关阅读:
    比较身高-第15届蓝桥杯第一次STEMA测评Scratch真题精选
    设计模式之状态模式
    Java-对象到底占多少个字节?计算规则是什么?
    YC-Framework版本更新:V1.0.9
    啃下大骨头——排序(一)
    LVM使用与管理
    二叉查找树(binary search tree)(难度7)
    基于springboot实现校园医疗保险管理系统【项目源码】
    跨域问题详解:CORS问题+解决办法
    为Ubuntu18.04云服务器创建sudo用户
  • 原文地址:https://blog.csdn.net/u010775335/article/details/126876185