java - 如何修复 JSSC 的 java.lang.UnsatisfiedLinkError? (需要硬 float ?)

标签 java linux

我在 JAR 中有一个 Java 应用程序需要使用 JSSC(在 SOPine 板上的 Ubuntu 上)通过串行通信。它抛出以下 java.lang.UnsatisfiedLinkError 异常:

Exception in thread "CommThread" java.lang.UnsatisfiedLinkError: /root/.jssc/linux/libjSSC-2.7_armsf.so: /root/.jssc/linux/libjSSC-2.7_armsf.so: cannot open shared object file: No such file or directory
    at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
    at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2430)
    at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2487)
    at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2684)
    at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2617)
    at java.base/java.lang.Runtime.load0(Runtime.java:767)
    at java.base/java.lang.System.load(System.java:1831)
    at jssc.SerialNativeInterface.<clinit>(SerialNativeInterface.java:172)
    at jssc.SerialPort.<init>(SerialPort.java:118)
    at com.company.comm.transport.serial.CommSerial.initialize(CommSerial.java:51)
    at com.company.product.adapters.comm.Communicator.connect(Communicator.java:73)
    at com.company.product.services.comm.CommThread.run(CommThread.java:18)

TL;DR:如果您不想阅读几天的疑难解答,请跳至答案。


我在 Eclipse 中导出我的 JAR 文件,并将 jssc.jar 添加到类路径中项目的 Java 构建路径的库中,并将其包含在导出的条目中。

我确认文件 libjSSC-2.7_armsf.so 在那里:

sudo ls –la /root/.jssc/linux/
drwxr-xr-x 2 root root  4096 Sep 23 14:41 .
drwxr-xr-x 3 root root  4096 Sep 20 15:39 ..
-rw-r--r-- 1 root root 10539 Sep 20 15:39 libjSSC-2.7_armsf.so

我能找到的与我的问题最接近的答案是 Stack Overflow 问题 unsatisfied link error runnable jar referencing jssc library .我确认我正在使用的 SOPine 板有一个 VFPv4 Floating Point Unit ,包含目录/lib/arm-linux-gnueablhf/,我安装了 JDK bellsoft-java11:armhf(来自 dpkg -l),所以我不清楚它为什么使用 libjSSC-2.7_armsf .so 而不是 libjSSC-2.7_armhf.so,后者位于同一个 jssc.jar 中。

我尝试在/root/.jssc/linux/目录下添加libjSSC-2.7_armhf.so,安装libjssc-java到linux,修改LD_LIBRARY_PATH和-Djava.library.path为指向另一个目录,但它抛出相同的异常,它无法找到 libjSSC-2.7_armsf.so。

我正在使用以下命令以 pine 用户运行 JAR 文件:

sudo java -jar product-0.1.0.jar &> output-0.1.0_1.txt

编辑 10/2/2019: 我试图通过删除 libjSSC-2.7_armsf.so 来更改它正在使用的 JSSC 共享库,使用 sudo apt install libjssc-java 在本地安装 jssc,并使用 LD_LIBRARY_PATH 和 -Djava.library.path 来关注我的程序正在运行新库,但它仍在请求 libjSSC-2.7_armsf.so。我打算将 Eclipse 项目配置为不将 JSSC JAR 文件与我的项目导出的 JAR 文件打包,然后尝试再次运行它。

编辑 10/7/2019: 上周,我决定创建一个简单的 HelloSerial.java 程序来减少潜在的依赖性。代码如下:

import jssc.SerialPortList;

public class HelloSerial {

    static {
        System.out.println("HelloSerial: loading JSSC");
        try {
            System.load("/root/.jssc/linux/libjSSC-2.7_armhf.so");
            System.out.println("HelloSerial: loading JSSC");
        } catch (UnsatisfiedLinkError e) {
            System.err.println("Native core library failed to load.\n" + e);
            System.exit(1);;
        }
    }

    public static void main(String[] args) {
        System.out.println("HelloSerial: start");

        String[] portNames = SerialPortList.getPortNames();
        System.out.println("HelloSerial: listing " + portNames.length + " port names");
        for(int i = 0; i < portNames.length; i++){
            System.out.println(portNames[i]);
        }

        System.out.println("HelloSerial: end");
    }
}

这是在 Linux 系统中编译和运行它的输出:

$ sudo javac -classpath .:jssc.jar HelloSerial.java
$ sudo java -cp jssc.jar:. HelloSerial
HelloSerial: loading JSSC
HelloSerial: loading JSSC
HelloSerial: start
Exception in thread "main" java.lang.UnsatisfiedLinkError: /root/.jssc/linux/libjSSC-2.7_armsf.so: /root/.jssc/linux/libjSSC-2.7_armsf.so: cannot open shared object file: No such file or directory
    at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
    at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2430)
    at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2487)
    at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2684)
    at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2617)
    at java.base/java.lang.Runtime.load0(Runtime.java:767)
    at java.base/java.lang.System.load(System.java:1831)
    at jssc.SerialNativeInterface.<clinit>(SerialNativeInterface.java:172)
    at jssc.SerialPortList.<clinit>(SerialPortList.java:43)
    at HelloSerial.main(HelloSerial.java:20)

即使我明确使用 System.load 来加载共享库的硬浮点版本,它仍然默认尝试使用软浮点。是什么迫使它使用软 float 版本?所有库(包括 JDK)都使用 armhf、arm64 或全部使用 dpkg -l

编辑 10/8/2019: 我发现 JSSC 在其 SerialNativeInterface 中使用逻辑类来确定要使用哪个共享库(这只是显示相关的代码行):

79  static {
80      String libFolderPath;
81      String libName;
82
83      String osName = System.getProperty("os.name");
84      String architecture = System.getProperty("os.arch");
85      String userHome = System.getProperty("user.home");
86      String fileSeparator = System.getProperty("file.separator");
87      String tmpFolder = System.getProperty("java.io.tmpdir");
...
118     else if(architecture.equals("arm")) {//since 2.1.0
119         String floatStr = "sf";
120 >>>>    if(javaLibPath.toLowerCase().contains("gnueabihf") || javaLibPath.toLowerCase().contains("armhf")){
121             floatStr = "hf";
122         }
123         else {
...
139         }
140         architecture = "arm" + floatStr;
141     }
142
143     libFolderPath = libRootFolder + fileSeparator + ".jssc" + fileSeparator + osName;
144     libName = "jSSC-" + libVersion + "_" + architecture;
145     libName = System.mapLibraryName(libName);

重要的部分在第 120 行,根据 java.library.path 是否包含 gnueabihf 或 armhf 路径,选择 ARM 的库是软浮点还是硬浮点。包括以下代码行会显示这些路径:

System.out.println("HelloSerial: java.library.path " + System.getProperty("java.library.path"));

这输出:

HelloSerial: java.library.path /usr/java/packages/lib:/lib:/usr/lib

看起来像 /lib/gnueabihf 这样的 gnueabihf 或 armhf 路径没有被使用,所以我需要添加一个作为占位符。

使用 sudo java -D.java.library.path=".:/lib/gnueabihf"-jar HelloSerial-1.0.0.jar 有效。

我会看看将来是否可以将 /lib/gnueabihf 永久添加到 java.library.path 中。

最佳答案

JSSC 在其 SerialNativeInterface 中使用逻辑类来确定要使用哪个共享库。对于具有 ARM 架构的操作系统,它会检查 java.library.path 以查看路径中是否包含 gnueabihf 或 armhf。如果没有,它将改用 soft float 共享库。

我当前的 java.library.path 不包含任何一个,所以我使用以下命令将现有的 /lib/gnueabihf 目录添加到路径中:

$ sudo java -D.java.library.path=".:/lib/gnueabihf" -jar HelloSerial-1.0.0.jar

this article 中列出了其他加载路径的方法或者您可以在线搜索该信息。您可以使用 $ java -XshowSettings:properties 来确认它包含在 java.library.path 中。

关于java - 如何修复 JSSC 的 java.lang.UnsatisfiedLinkError? (需要硬 float ?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58118965/

相关文章:

linux - 我的 $PATH 和 bash 命令遇到问题

linux - 需要澄清十二要素应用程序声明中的第八要素和守护进程

linux - 如何使用 Ansible 安装 MongoDB?

java - 距离小于5米的半正矢公式

java - Linux 上的 JSCH 抛出 java.awt.HeadlessException

java - 应用程序在外部 Tomcat 上启动之前进行 Spring Boot 日志记录

Javafx文本区域滚动 Pane 边框颜色问题

java - 缺少/不可用依赖项的服务

c - 使用四个不同端口的套​​接字处理连接

ruby - RVM Ruby 2.0.0 在 Ubuntu 11 中安装失败