为了账号安全,请及时绑定邮箱和手机立即绑定

使用 RXTX 部署独立应用程序

使用 RXTX 部署独立应用程序

qq_笑_17 2023-07-28 10:45:57
我有一个现有的应用程序,通常通过 TCP 与其目标进行通信,但是新的要求规定也可以通过串行 COM 端口进行连接。该应用程序本身是完全独立的,即它是一个单一的jar文件,最终用户可以将其复制到可能需要的位置,然后双击启动。RXTX 似乎打破了这个模型,因为它需要在库路径中包含额外的DLL或SO本机插件;如果无法使用本机 Java 与串行端口进行通信,我如何打包我的应用程序(使用 ,aven),以便 RXTX 在运行时可用,只需双击 Jar 文件即可。java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path: [__CLASSPATH__] thrown while loading gnu.io.RXTXCommDriver
查看完整描述

1 回答

?
小怪兽爱吃肉

TA贡献1852条经验 获得超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您不希望您的产品因为您的库收到非法指令的信号而导致用户崩溃。我建议在可以控制构建环境的虚拟机上构建库 - 使用较旧的 CPU 型号创建虚拟机并在其上安装旧的操作系统版本。


您还需要注意/tmp使用noexec. 该设置或某些 SE Linux 设置可能会导致共享对象加载失败。


查看完整回答
反对 回复 2023-07-28
  • 1 回答
  • 0 关注
  • 100 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信