最近由于工作原因需要使用Java调用C++写的算法。在实验前主要在博客上欣赏他人的例子,总结起来实现这个过程主要的方法有两种JNI和JNA,而且总体来说大家使用JNI库比较多。试验环境为Ubuntu:18.04,编译器为IDEA和Clion。
利用JNI的主要步骤:(1)、使用Java先新建我们所需要的native方法的Java类;
public class HelloWorld {
public native String displayHelloWorld();
}
(2)、在src/main/java利用javah -classpath . -jni com.xxx.classname 生成JNI格式的头文件,项目是通过maven自动生成;
javah -classpath . -jni com.xxx.classname
(3)、在Clion中新建一个C++ Library,类型为shared即动态库,然后将生成的头文件拷贝到项目目录下,新建一个同名的CPP文件,需要引入 jni.h jni_md.h两个文件,将这两个文件从jdk安装路径的include和它的Linux拷贝至项目目录下,然后编写详细实现;头文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"/* Header for class com_xxx_HelloWorld */
#ifndef _Included_com_xxx_HelloWorld#define _Included_com_xxx_HelloWorld#ifdef __cplusplusextern "C" {
#endif/** Class: com_xxx_HelloWorld* Method: displayHelloWorld* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_com_xxx_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus}
#endif#endif
源文件如下:
#include "com_xxx_HelloWorld.h"
JNIEXPORT jstring JNICALL Java_com_xxx_HelloWorld_displayHelloWorld
(JNIEnv *env, jobject){
return (env)->NewStringUTF("String From C++");
}
(4)、对文件进行编译,
sudo gcc com_xxx_HelloWorld.cpp com_xxx_HelloWorld.h jni.h jni_md.h -fPIC -shared -o libtest.so
(5)、将生成的动态库.so拷贝至调用类的同级目录下;
sudo cp libtest.so ~/IdeaProjects/sparkjava/src/main/java/com/xxx
(6)、在Java类中调用动态库,拷贝至目录下还不能直接运行,可能会出现:Exception in thread "main" java.lang.UnsatisfiedLinkError: no XXX in java.library.path,在Idea中需要选择Project Structure-->Libraries-->add 选择.so文件所在的目路并选择该文件,并确定。System.loadLibrary时库名称不能携带lib和.so,直接输入test即可(参照本例的库名称),调用代码如下:
/*** Hello world!**/
public class TestHello
{
static {
System.loadLibrary("test");
}
public native String displayHelloWorld();
public static void main(String []args){
System.out.println(new HelloWorld().displayHelloWorld());
}
}
(7)、点击运行之后控制台则会打印如下,表示调用成功。
String From C++
本次实验参考了很多博客而完成的,这个过程很简单,但是也会存在一些坑。特别是如果没有添加库引用则会报Exception in thread "main" java.lang.UnsatisfiedLinkError: no XXX in java.library.path这个错误。最后就是JNI这个东西为什么都是需要先编写包含native方法的java类,感觉设计有点反人类。