JNI示例

JNI是Java Native Interface的缩写,中文为JAVA本地调用,它允许Java代码和其他语言写的代码进行交互,主要是C和C++。由于在实现的时候遇到很多坑,所以记录下实现步骤,本文主要讲解在windows环境下实现,废话不多说,上代码。

1 环境

本文使用的环境:
jdk1.8
windows10,64位
mingw_64

2 java代码

public class JniDemo {

    public native void callCppMethod();

    public void callJavaMethod() {
        System.out.println("hello JNI");
    }

}

本文是JNI的一个简单的实现,通过java native方法调用c语言函数,再通过c函数调用java方法,即上图代码通过callCppMethod调用callJavaMethod方法。

3 生成.h头文件

进入JniDemo .java源文件执行命令:javac -h ./jni JniDemo .java
该命令是编译源文件,并在源文件的jni目录生成.h的头文件。
在这里插入图片描述
执行后结果:
在这里插入图片描述

4 编写c的实现

本文使用的c的开发工具为Visual Studio 2013
Visual Studio 2013下载链接
提取码:nvg7

安装好后创建项目:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
拷贝头文件com_jt_learn_jni_JniDemo.h到项目的头文件目录,如下图
在这里插入图片描述
在这里插入图片描述
此时打开头文件是有报错的,需要引入两个头文件jni.h和jni_md.h;
jni.h文件在:JAVA_HOME/include
jni_md.h文件在:JAVA_HOME/include/win32
步骤如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
添加完成后报错消失。

创建.c文件实现头文件中的方法,如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打开com_jt_learn_jni_JniDemo.c 引入头文件后发现报错
在这里插入图片描述
这是由于我们刚刚直接将头文件复制进来的原因,现在找不到,需要将刚刚生成的头文件所在目录添加进来。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
编辑com_jt_learn_jni_JniDemo.c文件,实现调用java的callJavaMethod方法。

#include "com_jt_learn_jni_JniDemo.h"

/*
抛出RuntimeException
*/
void throwRuntimeException(JNIEnv *jEnv, const char *msg) {
    JNIEnv env = *jEnv;

    jclass clazz = env->FindClass(jEnv, "java/lang/RuntimeException");

    env->ThrowNew(jEnv, clazz, msg);
}

/*
通过c++调用java方法
*/
JNIEXPORT void JNICALL Java_com_jt_learn_jni_JniDemo_callCppMethod
(JNIEnv *jEnv, jobject jObj){

    JNIEnv env = *jEnv;

    /* 获取类的字节码 */
    jclass jniDemoClass = env->GetObjectClass(jEnv, jObj);

    if (NULL == jniDemoClass) {
        throwRuntimeException(jEnv, "获取类字节码失败");
    }

    /* 获取需要指向的函数 */
    jmethodID callJavaMethod = env->GetMethodID(jEnv, jniDemoClass, "callJavaMethod", "()V");
    if (NULL == callJavaMethod) {
        throwRuntimeException(jEnv, "获取运行的JAVA方法ID失败");
    }

    /* 执行方法 */
    env->CallVoidMethod(jEnv, jObj, callJavaMethod);



}

5 生成动态链接库

5.1 安装gcc

inux 略.
windows:
首先下载mingw:
mingw_64位最新下载地址:mingw_64位最新版下载地址
mingw_32最新版下载地址:mingw_32位最新版下载地址
下载后需要安装。
官网下载比较慢,提供百度网盘的一个压缩包ming-w64-v7.0.0:
ming-w64-v7.0.0.7z 提取码:9ak0
下载后解压缩将bin目录配置到环境变量中
在这里插入图片描述
在这里插入图片描述

5.2 生成动态链接库

linux:

gcc -shared -fpic -I /JAVA_HOME/include com_jt_learn_jni_JniDemo.c -o /JAVA_HOME/bin/libcom_jt_learn_jni_JniDemo.so

将JAVA_HOME修改为自己的jdk目录
-I 给gcc添加自定义的头文件的路径。
生成的库文件名必须以lib开始,加载的时候不用lib
System.loadLibrary(“com_jt_learn_jni_JniDemo”);
生成动态链接库com_jt_learn_jni_JniDemo.so,动态链接库需要生成在jvm能加载到的地方,如果不知道放哪,可通过打印参数看jvm默认从哪些位置加载,即将com_jt_learn_jni_JniDemo.so拷贝到下面java代码输出的一个目录。

System.out.println(System.getProperty("java.library.path"));

windows:
找到com_jt_learn_jni_JniDemo.c文件目录,
在这里插入图片描述
将com_jt_learn_jni_JniDemo.h拷贝到com_jt_learn_jni_JniDemo.c目录
在这里插入图片描述
进入该目录命令窗口,执行命令:

gcc -c -I D:\jdk\jdk1.8.0_211-64\include -I D:\jdk\jdk1.8.0_211-64\include\win32 com_jt_learn_jni_JniDemo.c

在这里插入图片描述
执行完上述命令会生成com_jt_learn_jni_JniDemo.o文件。如下图
在这里插入图片描述
然后执行命令:

gcc -Wl,--add-stdcall-alias -shared -o com_jt_learn_jni_JniDemo.dll com_jt_learn_jni_JniDemo.o

在这里插入图片描述
执行完上述命令生成com_jt_learn_jni_JniDemo.dll文件
在这里插入图片描述
将com_jt_learn_jni_JniDemo.dll文件拷贝到jvm能够加载动态链接库的地方即下面代码输出的目录中的一个:
System.out.println(System.getProperty(“java.library.path”));

在这里插入图片描述

6 加载动态链接库,执行本地方法

public class App {
    public static void main(String[] args) {
        // 打印加载动态链接库的目录
        System.out.println(System.getProperty("java.library.path"));
        // 加载动态链接库
        System.loadLibrary("com_jt_learn_jni_JniDemo");
        // 调用本地方法
        new JniDemo().callCppMethod();
    }
}

执行main方法:
在这里插入图片描述
可以看到通过调用本地方法,调用了c的实现,在c中又调用了java方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值