最近用到了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
- #include
-
-
- 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