使用RXTX部署独立的应用程序

时间:2019-09-12 10:37:24

标签: java maven java-native-interface rxtx

我有一个现有的应用程序,该应用程序通常可以通过TCP与目标服务器进行通信,但是新的要求规定也可以通过串行COM端口进行连接。

该应用程序完全是独立的,因为它是单个 jar 文件,最终用户可以将其复制到可能需要的位置,然后双击以启动。

似乎RXTX打破了这种模型,因为它需要在库路径中包含其他 DLL SO 本机插件;如果无法使用本机Java与串行端口进行通信,那么如何通过双击Jar文件来打包我的应用程序(使用.aven),以便RXTX在运行时可用。

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

1 个答案:

答案 0 :(得分: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位OS上运行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的兼容性。您需要编译库,以便它们在较旧的OS版本和较旧的CPU上运行。如果您在新CPU上的Centos 7上构建,则尝试在Centos 6或更旧的CPU上运行的人将会遇到问题。您不希望您的产品在用户面前崩溃,因为您的库收到了一条SIGILL信号来指示非法指令。我建议在可控制构建环境的VM上构建库-使用较旧的CPU模型创建VM并在其上安装较旧的OS版本。

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