一、基础概念
1、JNI(Java Native interface):sun公司提供的JNI是Java平台的一个功能强大的接口,实现java和操作系统本地代码的相互调用功能,系统本地代码通常是由其他语言编写的,如C++。
二、JNI使用步骤
1、定义一个Java的native方法。
2、使用jdk的javah工具,生成包含native方法类的C/C++头文件(.h)。
3、创建C++项目,引入生成的C/C++头文件(.h),编写C/C++源文件(.cpp)实现逻辑,生成动态链接库(DLL)。
4、将DLL文件放到系统环境变量PATH配置的路径下(如:jdk的bin或者自己新增一个路径专门放DLL文件)。
5、Java加载DLL文件,调用native方法。
三、完整过程示例
1、创建Java项目,编写一个带有native的类
package cn.test;
public class TestJni {
public native void sayHello();
}
2、编译上java文件,通过javah生成C++头文件
(1)、点击compile,编译项目,生成class文件
(2)、进入编译项目的target/classes目录下,通过javah生成C++头文件
命令:javah cn.test.TestJni
说明:TestJni指的是TestJni.class文件,不是TestJni.java文件,一定要先编译。
如果还有路径层级,使用.连接。如: cn.zw.test.TestJni
(3)、查看头文件
3、创建C++的动态DLL项目,生成DLL文件
(1)、下载Visual Studio 2022工具(其他版本Visual Studio也行,能编译运行C++项目即可),如下标
(2)、新建项目,选择DLL动态链接库,点击下一步
(3)、配置项目如下图,项目名称无需一致,点击创建
(4)、新建C++动态链接库DLL项目如下
(5)、配置项目属性,在项目名称上右键(上图的右侧,解决方案资源管理器下的Dll1上右键),打开属性页面,配置64位,如下
(6)、添加java生成的头文件到C++项目中
因为生成的头文件引用了jni.h,jni.h中又引用了jni_md.h,所以这两个文件也要放到C++项目中,这两个文件分别在jdk目录的include下和win32下,如下图
最终引入3个文件如下:
(7)、在visual Studio编辑器中,右侧项目的头文件上,点击右键,选择添加,选择现有项,选择上一步添加的3个头文件,引入到工程中
引入后如下:
(8)、修改引入配置
在生成头文件中引入jni.h原本使用<>,需要修改成"“,如上图为最终引入效果,使用”"
在jni.h中,引入jni_md.h文件也是需要将<>改成""
说明:因为<>是从系统中查找文件并加载,""为从当前项目查找并加载
(9)、在源文件上,创建source.cpp文件,编写source.cpp文件,覆写java定义的native方法
第1行:引入pch.h,这个是项目需要,直接写即可,其他文件也有,copy即可
第2行:引入生成的头文件,因为需要覆写这个文件的方法
第3,4行:定义标准的输入输出
第6行的方法:覆写方法的逻辑函数,直接从生成的头文件中copy这个方法过来,参数上env和obj两个参数,在加上方法体{},在方法体内编写C++实现逻辑,如输出一句话:hello Java,I am C++。
(10)、在项目Dll1上右键,点击生成,运行成功后,可以生成dll文件
上运行日志的路径找到Dll文件
4、将Dll文件放到系统变量Path中添加的路径下,本例直接放到jdk的bin下
5、在java项目中,调用native方法
如下就正常输出了C++中的结果。
因为系统(windows,linux)大部分逻辑和一些本地方法都是C++语言开发的,java并不能直接调用,所以一定场景下我们需要通过JNI的方式去实现调用C++的方法。
注意:本地java中最终想要运行成功,就一定要有C++环境,要装VisualStudio,否则即使生成了Dll文件,也可能存在找不到类库的问题。
扩展:
上面的案例仅是无参情况下的JNI调用,如果有参的调用,需要注意如下:
1、定义native方法带参数和返回类型
2、覆写C++的方法还是直接copy过去后,添加参数和通过return放回
3、测试传参和计算
学海无涯苦作舟!!!