Java调用C++库

2020-05-25  本文已影响0人  南岩飞雪

问题

https://gist.github.com/santa4nt/4a8fd626335e36c94356
MAC电脑,使用这里的例子,指定好JAVA_INC路径之后,执行脚本报错

Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at HelloJNI.<clinit>(HelloJNI.java:4)

解决

makerun.sh 脚本中生成的 libhello.so 改成 libhello.dylib 即可

原因

一层一层分析

public class HelloJNI {
    static {
        System.loadLibrary("hello"); 
    }
......
g++ -std=c++11 -shared -fPIC -I$JAVA_INC -I$JAVA_INC/linux HelloJNIImpl.cpp -o libhello.so
java -Djava.library.path=. HelloJNI
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at HelloJNI.<clinit>(HelloJNI.java:4)
  1. 很显然,问题是没有在 java.library.path 的路径中 找到 libname 为 hello 的动态库,我们在代码里打印一下 java.library.path 和 实际匹配的 libname,发现path ok,libname 为 libhello.dylib,并非libhello.so;
    查看jdk源码发现,jdk对Windows、Mac、Linux操作系统中的 libname 处理各不相同,以前只关注到了 Windows 和 Linux 的区别。
打印变量
public class HelloJNI {
    static {
        System.out.println(System.getProperty("java.library.path"));
        System.out.println(System.mapLibraryName("hello"));
        System.loadLibrary("hello"); 
    }
......
输出结果
.
libhello.dylib
jdk源码
                // Set the lib prefix and suffix based on the OS
                if (osName.startsWith("Windows")) {
                    libPrefix = "";
                    libSuffix = ".dll";
                } else if (osName.startsWith("Mac")) {
                    libPrefix = "lib";
                    libSuffix = ".dylib";
                } else if (osName.startsWith("Linux")) {
                    libPrefix = "lib";
                    libSuffix = ".so";
                }
上一篇 下一篇

猜你喜欢

热点阅读