【问题标题】:Deploying a self-contained application with RXTX使用 RXTX 部署一个独立的应用程序
【发布时间】:2019-09-12 10:37:24
【问题描述】:

我有一个现有的应用程序,它通常通过 TCP 与其目标进行通信,但是新的要求表明连接也可以通过串行 COM 端口进行。

目前的应用程序是完全独立的,即它是一个单独的 jar 文件,最终用户可以将其复制到可能需要的地方,然后双击启动。

RXTX 似乎打破了这种模式,因为它需要在库路径中包含额外的 DLLSO 原生插件;如果无法使用本机 Java 与串行端口通信,我如何打包我的应用程序(使用 ,aven),以便 RXTX 在运行时可用,只需双击 Jar 文件。

java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path: [__CLASSPATH__] thrown while loading gnu.io.RXTXCommDriver

【问题讨论】:

    标签: java maven java-native-interface rxtx


    【解决方案1】:

    您需要将库打包到您的 jar 文件中,然后将其解压缩,将其写为文件,然后加载它(import 语句和异常/错误处理省略):

    public class YourClass {
        static {
            // path to and base name of the library in the jar file
            String libResourcePath = "path/to/library/yourLib.";
    
            // assume Linux
            String extension = "so";
    
            // Check for Windows
            String osName = System.getProperty("os.name").toLowerCase();
            if (osName.contains("win"))
                extension = "dll";
    
            libResourcePath += extension;
    
            // find the library in the jar file
            InputStream is = ClassLoader.getSystemResourceAsStream( libResourcePath );
    
            // create a temp file for the library
            // (and we need the File object later so don't chain the calls)
            File libraryFile = File.getTempFile("libName", extension);
    
            // need a separate OutputStream object so we can
            // explicitly close() it - can cause problems loading
            // the library later if we don't do that
            FileOutputStream fos = new FileOutputStream(libraryFile);
    
            // assume Java 9
            is.transferTo(fos);
    
            // don't forget these - especially the OutputStream
            is.close();
            fos.close();
    
            libraryFile.setExecutable(true);
            libraryFile.deleteOnExit();
    
            // use 'load()' and not 'loadLibrary()' as the
            // file probably doesn't fit the required naming
            // scheme to use 'loadLibrary()'
            System.load(libraryFile.getCanonicalPath());
        }
    
        ...
    }
    

    请注意,您需要为您支持的每个操作系统和架构添加库版本。这包括 32 位和 64 位版本,因为很可能在 64 位操作系统上运行 32 位 JVM。

    您可以使用os.arch 系统属性来确定您是否在 64 位 JVM 中运行。如果该属性中包含字符串"64",则说明您在64 位JVM 中运行。假设它是 32 位 JVM 是非常安全的:

    if (System.getProperty("os.arch").contains("64"))
        // 64-bit JVM code
    else
        // 32-bit JVM code
    

    如果您正在自定义类加载器,您可能还必须使用 YourClass.class.getClassLoader().getResourceAsStream()

    注意操作系统和 CPU 的兼容性。您需要编译您的库,以便它们在较旧的操作系统版本和较旧的 CPU 上运行。如果你在新 CPU 上构建 Centos 7,尝试在 Centos 6 或旧 CPU 上运行的人会遇到问题。您不希望您的产品在用户身上崩溃,因为您的库收到了 SIGILL 非法指令信号。我建议在可以控制构建环境的 VM 上构建库 - 使用旧 CPU 模型创建 VM 并在其上安装旧操作系统版本。

    您还需要注意挂载/tmpnoexec 的Linux 系统。该或某些 SE Linux 设置可能会导致共享对象加载失败。

    【讨论】:

    • 我最终切换到 jSerialComm,在阅读了他们的源代码后,它似乎在做一些非常相似的事情。非常感谢您的回答,我可能会在不久的将来某个时候切换回 RXTX。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 2016-02-04
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多