美文网首页
JNI入门实践

JNI入门实践

作者: 河北漂 | 来源:发表于2021-07-10 21:21 被阅读0次

    JNI 全称 Java Native Interface。Java本地方法接口,它是Java语言允许Java代码与C、C++代码交互的标准机制。维基百科是这样解释的:“当应用无法完全用Java编程语言实现的时候,(例如,标准Java类库不支持的特定平台特性或者程序库时),JNI使得编程者能够编写native方法来处理这种情况”。这就意味着,在一个Java应用程序中,我们可以使用我们需要的C++类库,并且直接与Java代码交互,而且在可以被调用的C++程序内,反过来调用Java方法(回调函数)。

    JNI的优势

    • 操作系统相关 JNI使得一些"过程"无需在Java中实现。例如,硬件敏感的,或者直接与操作系统API关联的命令。
    • 性能优化 底层的库,如图形,计算,各种类型的渲染等等,可以提高应用的运行性能。
    • 既有实现 已经有大量的库已经被实现,编程者可直接使用,不用再自行编写。这里的库指的是用其他编程语言实现的程序库,例如IO流或者线程等底层与OS交互的操作都是由C/C++实现的。

    JNI的实现

    1、定义Java类

    定义一个带native方法的java类如:

    /**
     * @author jack
     */
    public class JniCompileTest {
        /**
         * 执行jni调用
         */
        public native Map<String, String> excute(String param1, Object param2);
    }
    
    2、生成头文件

    在项目的根目录下执行javah命令

    javah -classpath . -jni com.package.jni.test.JniCompileTest
    

    完成后,会在根目录下生成一个同名的.h结尾的头文件。

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_package_jni_test_JniCompileTest */
    
    #ifndef _Included_com_package_jni_test_JniCompileTest
    #define _Included_com_package_jni_test_JniCompileTest
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_package_jni_test_JniCompileTest
     * Method:    excute
     * Signature: (Ljava/lang/String;Ljava/lang/Object;)Ljava/util/Map;
     */
    JNIEXPORT jobject JNICALL Java_com_package_jni_test_JniCompileTest_excute
      (JNIEnv *, jobject, jstring, jobject);
    #ifdef __cplusplus
    }
    #endif
    #endif
    
    3、引入头文件

    在头文件中的 jni.h 如果在编译动态链接库(.so文件)的时候找不到,可以去本地的JDK目录中的include文件下找到两个文件:jni.hjni_md.h 。然后拷贝到与JniCompileTest.h同目录下。

    修改引入方式

    #include <jni.h> 
    

    改为

    #include "jni.h" 
    

    然后可以定义一个同名的cpp源码文件,开发JNI的cpp实现了

    //
    // Created by jack on 2021/7/10.
    //
    #include "com_package_jni_test_JniCompileTest.h"
    
    JNIEXPORT jobject JNICALL Java_com_package_jni_test_JniCompileTest_excute
            (JNIEnv *env, jobject, jstring, jobject){
        // do something
        return NULL;
    }
    
    4、编译动态链接库

    在clion中构建一个cmake项目,然后写CMakeLists.txt

    project(JniCompileTest C CXX)
    cmake_minimum_required(VERSION 2.8.0)
    # 这里用自己的目录即可
    INCLUDE_DIRECTORIES(src/main/cpp/jnilib/include/)
    
    FILE(GLOB SRC_JNI_LIBRARY src/main/cpp/jnilib/src/*.cpp)
    FILE(GLOB HEADER_JNI_LIBRARY src/main/cpp/jnilib/include/*.h)
    
    add_library(JniCompileTest SHARED ${HEADER_JNI_LIBRARY} ${LIST_SRC} ${SRC_JNI_LIBRARY})
    

    完成后执行编译

    5、java引入动态链接库

    java 使用动态库,需要用System类load,例如在上面的类的构造方法的中加入即可。

    /**
     * @author jack
     */
    public class JniCompileTest {
        public JniCompileTest(){
            // mac下文件为JniCompileTest.dylib
            File outputJNIFile = new File("/user/jack/JniCompileTest.so");
            System.load(outputJNIFile.getAbsolutePath());
        }
        /**
         * 执行jni调用
         */
        public native Map<String, String> excute(String param1, Object param2);
    }
    

    结尾

    JNI的封装完成,但是在JNI的开发中,还是不少注意的地方,例如JNI对象的定义,如何解析java传递来的对象,如果回调java方法等。

    相关文章

      网友评论

          本文标题:JNI入门实践

          本文链接:https://www.haomeiwen.com/subject/weacpltx.html