Java利用JNI调用C++(dll/so)函数
JNI
(Java Native Interface ,Java本地接口),使用JNI
规范可以与其它语言程序进行交互,调用本地方法、访问本地资源,从而扩展Java的功能。
- 通过JNI调用本地代码,利用本地代码的高效性和底层功能来完成特定任务,譬如:使用
C
来控制Nginx
、设置开机启动。 - 通过JNI可以访问本地系统资源,如文件、网络接口等。使得Java程序可以直接与本地环境进行交互,实现更加灵活和强大的功能。

1 JNI操作步骤
-
创建Java本地方法
- 在Java代码中,通过native关键字声明一个本地方法
-
生成Java本地接口
- 使用Java的javah命令,根据Java类文件生成对应的本地接口文件
-
实现Java本地接口
- 使用
Visual Studio
将本地代码编译成动态库
- 使用
-
加载并调用dll文件中的方法
- 加载
System.loadLibrary("libname")
或者System.load("path")
- 调用本地方法
- 加载
2 实现
2.1 创建本地方法
arduino
package cn.chao.datamsg;
public class DataMsgFormatTest {
static {
System.loadLibrary("DataMsgFormat");
}
public native String version();
public native String base64(String plain);
public static void main(String[] args) {
new DataMsgFormatTest().version();
}
}
2.2 生成Java本地接口
javah -encoding utf-8 -classpath . -jni cn.chao.datamsg.DataMsgFormatTest


arduino
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_chao_datamsg_DataMsgFormatTest */
#ifndef _Included_cn_chao_datamsg_DataMsgFormatTest
#define _Included_cn_chao_datamsg_DataMsgFormatTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: cn_chao_datamsg_DataMsgFormatTest
* Method: version
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_version
(JNIEnv *, jobject);
/*
* Class: cn_chao_datamsg_DataMsgFormatTest
* Method: base64
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_base64
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
-
JNIEXPORT
和JNICALL
是JNI
宏,用于导出JNI
函数 -
Java_cn_chao_datamsg_DataMsgFormatTest_version
是Java本地方法的名称cn_chao_datamsg
是类路径DataMsgFormatTest
是类名version
是方法名- 可以使用
JNIEnv
和jobject
参数来访问Java虚拟机和对象 jstring
是JNI类型,表示Java的String类型
3 实现Java本地接口
使用的是
Visual Studio 2010 专业版
以及Win7系统

- 新建项目
Win32项目
的空项目



- 创建的项目目录

- 在
头文件
文件夹中,引入 《2.2 生成Java本地接口》 生成的.h
文件

- 还需要引入
包目录
,为jdk/include
与jdk/include/win32



- 编写实现函数
cpp
文件
c
#include <iostream>
#include <string.h>
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: cn_chao_datamsg_DataMsgFormatTest
* Method: version
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_version
(JNIEnv * env, jobject obj){
std::string data_msg_version = "1.0.0";
return env->NewStringUTF(data_msg_version.c_str());
}
/*
* Class: cn_chao_datamsg_DataMsgFormatTest
* Method: base64
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_base64
(JNIEnv * env, jobject obj, jstring str){
std::string data_msg_version = "1.0.0";
return env->NewStringUTF(data_msg_version.c_str());
}
#ifdef __cplusplus
}
#endif
- 生成
64位和32位
的dll
文件




4 测试Java调用接口
- System.load("/proc/DataMsgFormat.dll")
- System.loadLibrary("DataMsgFormat");
