• 一个JNI的Demo,linux上下载就可以用


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

    1. sudo apt install openjdk-11-jdk
    2. sudo apt install default-jdk
    1. $java -version
    2. openjdk version "11.0.20.1" 2023-08-24
    3. OpenJDK Runtime Environment (build 11.0.20.1+1-post-Ubuntu-0ubuntu120.04)
    4. 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

    如果下载不了,就从下面的代码自己粘贴一下。

    压缩包中的文件内容如下:

    1. ├── build.sh
    2. ├── demo
    3. │   └── hello.java
    4. ├── demo_hello.cpp
    5. ├── demo_hello.h
    6. └── Main.java

     demo是文件夹

    demo/hello.java的内容

    1. package demo;
    2. public class hello {
    3. {
    4. // 加载.so
    5. //System.setProperty("java.library.path", "./");
    6. //System.load("/home/demo/work/java/libhello.so"); //不要使用load,load需要全路径
    7. System.loadLibrary("hello"); //load libhello.so
    8. }
    9. /**
    10. * 就这个natice关键字.标记了这个接口,看起来像是abstract
    11. */
    12. public native int sayHello(String msg);
    13. }

     demo_hello.cpp的内容:

    1. #include "demo_hello.h"
    2. #include
    3. #include
    4. JNIEXPORT int JNICALL Java_demo_hello_sayHello(JNIEnv *env, jobject obj, jstring inJNIStr){
    5. const char *inCStr = env->GetStringUTFChars(inJNIStr, NULL);
    6. if (NULL == inCStr) return 1;
    7. using namespace std;
    8. cout << "Hello World"<< endl;
    9. cout << inCStr << endl;
    10. return 0;
    11. }

    Main.java的内容:

    1. import demo.*;
    2. public class Main {
    3. public static void main(String[] args) {
    4. new demo.hello().sayHello("java");
    5. }
    6. }

    三、编译运行过程

    具体编译和运行的过程都写在build.sh中了,build.sh具体内容如下:

    1. export JAVA_HOME=/usr/lib/jvm/default-java
    2. javac -h . demo/hello.java
    3. g++ -fPIC -shared demo_hello.cpp -o libhello.so -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux"
    4. javac Main.java
    5. export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
    6. 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程序就可以看到输出结果:

    1. jni$ ./build.sh
    2. Hello World
    3. java

  • 相关阅读:
    线程池(重点)
    shell脚本耕升(一)
    【QT】窗口的大小标题图标设置
    双十一运动装备选购清单,今年最值得入手的运动好物
    【Vue】params和query的区别?实战两种路由传参方式
    强化您的应用安全,从app加固开始
    来!PyFlink 作业的多种部署模式
    C++的哈希 && 哈希表 && 哈希桶
    PyQT5 QMessageBox对话框设置
    将一维数组转为三维数组,html引入swiper并且自定义左右切换按钮
  • 原文地址:https://blog.csdn.net/v6543210/article/details/134051813