(一)JNI 基本流程、数据类型

版权声明:本文为博主原创文章,未经博主允许不得转载。

本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。

一、概述

JNI 全称 java native interface。

使用环境:当 java api 不能满足我们程序的需要的时候,比如算法计算,图像渲染中,效率要求非常高,又或者需要访问一些已有的本地库。

二、JNI 步骤

1.编写 native 方法

在 java 代码中申明 native 的方法。

public class JNIMain {

    public native static String getString();

}

2.生成 .h 文件

在命令行窗口中切换到项目的 src 目录下,使用 javah 命令生成对应的 .h 文件。

这里写图片描述

注:必须切到 src 这个目录,javah 后面跟的是包名与类名。

刷新项目:

这里写图片描述

生产的 .h 文件中的方法名java_类的全名_方法名 ,也可以手动进行生成。

3.复制 .h 头文件到 cpp 工程

把上方生成的 com_xiaoyue_JNIMain.h 文件复制到 C 项目工程所在文件目录中(这边采用的是 VS 创建 C 项目)。

这里写图片描述

在 VS 的项目结构中,添加 com_xiaoyue_JNIMain.h 文件。

这里写图片描述

这时候 com_xiaoyue_JNIMain.h 会报一些错误,需要进行修改。

4.复制 jni.h 和 jni_md.h

com_xiaoyue_JNIMain.h 需要用到 java 的两个 .h 文件,这两个头文件在 JDK 里面就有。

jni.h:
这里写图片描述

jni_md.h:
这里写图片描述

把这两个头文件按第三步复制到 C 项目工程下,同时进行导入。

5.修改 com_xiaoyue_JNIMain.h

修改 com_xiaoyue_JNIMain.h 文件下的 #include <jni.h>#include "jni.h"

这里写图片描述

6.实现 .h 头文件中的声明函数

新建一个 .c 文件,实现 .h 文件的申明。

#include "stdafx.h"

#include "com_xiaoyue_JNIMain.h"

JNIEXPORT jstring JNICALL Java_com_xiaoyue_JNIMain_getString
(JNIEnv *env, jclass jciz) {
    return (*env)->NewStringUTF(env, "Hello JNI");
}

7.生成一个dll 动态库

右击项目,选择属性。在属性窗口里设置项目类型为动态库。

这里写图片描述

设置预编译头不使用预编译头。(否则会报错)

这里写图片描述

右键生成 –> 重新生成解决方案。

这里写图片描述

这时候会生成 .dll 动态库,dll 是 window 环境下的动态库, so 是 linux 环境下的动态库。

这里写图片描述

8.在java中加载动态库

把生成的动态库拷贝到 java 项目工程里面。

这里写图片描述

在 java 代码中进行加载改动态库。

public class JNIMain {

    public native static String getString();

    static{
        System.loadLibrary("FirstApplication");
    }
}

9.触发 native 函数

JNI 的调用跟 java 普通方法的调用没有区别。

public class JNIMain {

    public native static String getString();

    static{
        System.loadLibrary("FirstApplication");
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(getString());
    }
}

结果:

这里写图片描述

三、分析

1.动态库和静态库

都是函数库

静态库:在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库:在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

2.JNIEnv

生成的 .h 文件中,方法有两个参数,第一个参数就是 JNIEnv。

这里写图片描述

右击选择跳转到定义处,可以发现这是定义在 jni.h 文件中(即我们从 jdk 下拷贝出来的)。

这里写图片描述

在 C 的情况下:JNIEnv 是一个指向 JNINativeInterface_ 的指针,而 JNINativeInterface_ 是一个结构体,里面包含众多的函数指针。可通过这些方法与 java 进行交互。所以通过 JNIEnv 可以调用到 java 的方法。

在 C ++ 的情况下, JNIEnv 就是一个 JNIEnv_ 变量,在 JNIEnv_ 里面包含一个 JNINativeInterface_ 的指针。

四、静态与非静态方法

上面写的方法是一个静态的,这边在添加一个非静态的方法。

java 代码:

public class JNIMain {

    public native static String getString();

    public native String getString2();

    static{
        System.loadLibrary("FirstApplication");
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(getString());

        JNIMain jniMain = new JNIMain();
        jniMain.getString2();
    }
}

.h 文件:

/*
 * Class:     com_xiaoyue_JNIMain
 * Method:    getString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_xiaoyue_JNIMain_getString
  (JNIEnv *, jclass);

/*
 * Class:     com_xiaoyue_JNIMain
 * Method:    getString2
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_xiaoyue_JNIMain_getString2
  (JNIEnv *, jobject);

主要区别是生成的 .h 文件第二个参数,静态的是 jclass, 非静态的是 jobject。

jclass 表示调用静态方法的类,在这边即 JNIMain。
jobject 表示调用非静态方法的对象,这边指创建出来的 JNIMain 的实例 jniMain。

五、数据类型

1.基本数据类型

这里写图片描述

2.引用类型

这里写图片描述

3.数据类型与签名

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值