最近用到了Java,需要用Java调用c++做的.so,搜了一下,有一个demo,但是这个demo有严重的问题。 加载.so的时候不好好地用 System.loadLibrary("hello");
他用System.load("hello");这个函数需要使用全路径。总是报这个错误:
Expecting an absolute path of the library:
真他么的。害人不浅。
这里我就做个demo,直接拿去用,就可以知道整个流程了。
如果不想太清楚也不要紧,用就行了。
谴责一个这个出来害人的博主。
JNI详解------完整Demo_java jni-CSDN博客
一、环境准备
ubuntu20.04
装jdk, 用default-jdk就可以。默认装的是jdk11
sudo apt install openjdk-11-jdk
sudo apt install default-jdk
$java -version
openjdk version "11.0.20.1" 2023-08-24
OpenJDK Runtime Environment (build 11.0.20.1+1-post-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 11.0.20.1+1-post-Ubuntu-0ubuntu120.04, mixed mode, sharing)
gcc g++ 这些就不用说了,肯定也要的。
sudo apt install build-essential
二、下载代码
可以在这下载
https://download.csdn.net/download/v6543210/88475296
如果下载不了,就从下面的代码自己粘贴一下。
压缩包中的文件内容如下:
├── build.sh
├── demo
│ └── hello.java
├── demo_hello.cpp
├── demo_hello.h
└── Main.java
demo是文件夹
demo/hello.java的内容
package demo;
public class hello {
{
// 加载.so
//System.setProperty("java.library.path", "./");
//System.load("/home/demo/work/java/libhello.so"); //不要使用load,load需要全路径
System.loadLibrary("hello"); //load libhello.so
}
/**
* 就这个natice关键字.标记了这个接口,看起来像是abstract
*/
public native int sayHello(String msg);
}
demo_hello.cpp的内容:
#include "demo_hello.h"
#include <iostream>
#include <string>
JNIEXPORT int JNICALL Java_demo_hello_sayHello(JNIEnv *env, jobject obj, jstring inJNIStr){
const char *inCStr = env->GetStringUTFChars(inJNIStr, NULL);
if (NULL == inCStr) return 1;
using namespace std;
cout << "Hello World"<< endl;
cout << inCStr << endl;
return 0;
}
Main.java的内容:
import demo.*;
public class Main {
public static void main(String[] args) {
new demo.hello().sayHello("java");
}
}
三、编译运行过程
具体编译和运行的过程都写在build.sh中了,build.sh具体内容如下:
export JAVA_HOME=/usr/lib/jvm/default-java
javac -h . demo/hello.java
g++ -fPIC -shared demo_hello.cpp -o libhello.so -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux"
javac Main.java
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
java -Djava.library.path=. Main
现在的java 11里面没有javah这个命令了,取尔代之的是 javac -h命令
JAVA_HOME就用这个/usr/lib/jvm/default-java就挺好,省得去查版本号。
demo_hello.cpp这个文件的名字你可以自己定,demo_hello.h这个文件是 javac -h 命令生成的。
./build.sh运行后会在目录中生成libhello.so
运行程序时指定 java.library.path为当前目录,可以直接从当前目录加载libhello.so
java -Djava.library.path=. Main
运行java程序就可以看到输出结果:
jni$ ./build.sh
Hello World
java