什么是JNI
JNI是Java Native Interface的缩写,中文为JAVA本地调用。使用JNI可以很方便的用我们的Java程序调用C/C++程序。
很多时候,某些功能用Java无法实现,比如说涉及到底层驱动的一些功能,这时候我们就可以利用JNI来调用C或者C++程序来实现,这就是JNI的强大之处。但是JNI也有它的缺点,使用java与本地已编译的代码交互,通常会丧失平台可移植性。
Java接口
public class hello {
{
System.load("C:\\Users\\Administrator\\IdeaProjects\\untitled1\\src\\Dll1.dll");
//加载其他函数的驱动,是个dll文件
}
public native void sayHello();
public static void main(String[] args){
new hello().sayHello();
}
}
可以看出,要想调用其他语言的接口,我们需要一个dll文件,那什么是dll文件?DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。
实现步骤
创建一个hello类,如下
public class hello {
public native void sayHello(); //声明一个原生函数,是由c/c++实现
public static void main(String[] args){
new hello().sayHello(); //调用该方法.
}
}
Dos命令编译
javac hello.java
javac -h -jni hello.java
//jdk10已经移除javah工具,相应的功能已经集成到javac中
效果如下
我们的目的是生成 . h文件
hello.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class hello */
#ifndef _Included_hello
#define _Included_hello
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: hello
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_hello_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
其中如下是C/C++函数接口,我们需要实现该方法
JNIEXPORT void JNICALL Java_hello_sayHello
(JNIEnv *, jobject);
使用VS创建DLL项目
这里我使用的是VS2019版本.
在默认生成的dllmain.cpp加入如下代码
#include "pch.h" //默认生成的
#include <iostream>
#include "jni.h" //需要加入的
#include "hello.h" //需要加入的
using namespace std;
JNIEXPORT void JNICALL Java_hello_sayHello
(JNIEnv*, jobject) {
cout << "Hello java" << endl;
}
该cpp文件原有代码可以保留
我们需要jni.h和hello.h这两个头文件,所以我们把这两个头文件放到该项目下。
其中jni.h在jdk在安装目录下的include文件夹里
hello.h是我们刚刚生成的,最终如下图所示:
问题是,使用vs默认生成的dll是32位的,这里我们需要使用64位的dll,不然会发生版本不兼容的情况。
生成Dll
在java文件中引用dll文件
这里填写的是dll的文件所在目录。
运行程序
总结
最终,输出的结果是Hello java,是我们用c++输出的,可见结果正确,我们也确实调用C/C++程序。