zoukankan      html  css  js  c++  java
  • JNI

    • JNI的存在价值:

    Java Native Interface(JNI)是Java语言的本地编程接口,是J2SDK的一部分。在java程序中,我们可以通过JNI实现一些用java语言不便实现的功能。通常有以下几种情况我们需要使用JNI来实现。

    • 标准的java类库没有提供你的应用程序所需要的功能,通常这些功能是平台相关的(如某些平台特有的功能)。
    • 你希望使用一些已经有的类库或者应用程序,而他们并非用java语言编写的(如:已有的c++功能库)
    • 程序的某些部分对速度要求比较苛刻,你选择用汇编或者c语言来实现并在java语言中调用他们(要求执行效率高的,java无法达到那种效率)

    不到万不得已不要使用JNI技术,一方面它需要你掌握更多的知识才可以驾驭(作为一个安卓开发者,要同时兼顾android以及c++开发,还是很难的),

    一方面使用了JNI你的程序就会丧失可移植性(因为有一部分功能是jni写的,用到了其他平台的特性,导致不能在任何平台上都能有一样的效果,就失去了跨平台的特性)。

      如果一句话概括JNI的存在意义:就是,让java调用c++以及c++回调java,jni是两者相互沟通的中介。

    • 几个关键词
    1.  cpp编程一般是基于头文件.h进行的,那么如何生成javaJni类对应的.h文件呢?

        javac,javah

        javac是将一个java文件编译成.class,javah则是将.class转化成.h. 这个.h头文件。之后,cpp按照这个h文件来编程,用c++代码来实现jni函数。

        下面以一个androidStudio project作为案例来看:   

    javac:

    如果你要将一个QPlayer.java文件编译成QPlayer.class.
    cmd命令写法为:javac 后面接上QPlayer.java文件的完整路径。
    如:javac F:jniResearchMyApplicationappsrcmainjava esthankcomjni20180205QPlayer.java
    运行之后,就会在QPlayer.java的旁边,生成一个QPlayer.class.

    javah:如图,

    1)切换到java目录(cd F:jniResearchMyApplicationappsrcmainjava)

    2)执行cmd:

    javah test.hank.com.jni20180205.QPlayer

    .h文件就会出现在java目录下。

    这个过程也称为静态注册Native方法。

     

    2.java和c++是两种不同的语言,他们的数据类型也不相同,那么JNI如何做到两者数据互通? 

    既然JNI可以沟通java和c++,那么他们两个的数据类型 不相同该怎么处理呢?JNI的方式是,使用一个中介。

    如图,java类型,本地类型(即c++类型),这里还有一个叫:JNI别名。

    我们看一下1)中生成的.h文件。以及原始的.java文件。

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class test_hank_com_jni20180205_QPlayer */
    
    #ifndef _Included_test_hank_com_jni20180205_QPlayer
    #define _Included_test_hank_com_jni20180205_QPlayer
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     test_hank_com_jni20180205_QPlayer
     * Method:    add
     * Signature: ()I
     */
    JNIEXPORT jint JNICALL Java_test_hank_com_jni20180205_QPlayer_add
      (JNIEnv *, jobject);
    
    /*
     * Class:     test_hank_com_jni20180205_QPlayer
     * Method:    getString
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_test_hank_com_jni20180205_QPlayer_getString
      (JNIEnv *, jobject);
    
    /*
     * Class:     test_hank_com_jni20180205_QPlayer
     * Method:    test1
     * Signature: (IJLjava/lang/String;)Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_test_hank_com_jni20180205_QPlayer_test1
      (JNIEnv *, jobject, jint, jlong, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    public class QPlayer {
        static {
            System.loadLibrary("qplayer");//这里,真实加载的文件其实是:libQplayer.so
        }
    
        public native int add();
    
        public native String getString();
    
        public native String test1(int a,long b,String c);
    }

     

        可以发现,java中的test1函数,三个参数分别是int,long,String,c++的h文件中,test1函数对应位置则是jint,jlong,jstring,这就是所谓的jni别名. 然而这里的jint,jlong,jstring并不是c++的int,long和string,而是jni.h中特别定制的(h文件最上面#include <jni.h>,说明引用了jni.h).

    3. 步骤1中说的是用java的jni类来生成头文件,然后用这个头文件来约束c++编程规范。那如果真实情况下,没有这个java jni类呢?也有办法:native方法动态注册,不依赖java jni类。 

      这部分需要对c++想当熟悉,笔者没做过c++相关工作,具体请看:https://www.jianshu.com/p/aba734d5b5cd,搜索关键字 动态注册。一般这部分工作还是由c++开发人员来写。

      

  • 相关阅读:
    Linux虚拟内存管理(glibc)
    linux kernel内存回收机制
    Linux的Cache Memory(缓存内存)机制
    imx6用文件io操作gpio
    imx6中iomux IO复用
    start with git
    Linux进程的虚拟内存区域划分
    关于函数返回值为指针类型的分析
    对LCD接口的认识
    LCD屏背光驱动调试心得---血的教训
  • 原文地址:https://www.cnblogs.com/hankzhouAndroid/p/8421113.html
Copyright © 2011-2022 走看看