我有一个现有的应用程序,通常通过 TCP 与其目标进行通信,但新要求规定也可以通过串行 COM 端口建立连接。
该应用程序本身是完全独立的,即它是一个 jar 文件,最终用户可以将其复制到可能需要的位置,然后双击启动。
看起来 RXTX 打破了这个模型,因为它需要额外的DLL或SO native 插件包含在库路径中;如果无法使用 native Java 与串行端口进行通信,我如何打包我的应用程序(使用 ,aven),以便 RXTX 在运行时可用,只需双击 Jar 文件即可。
java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path: [__CLASSPATH__] thrown while loading gnu.io.RXTXCommDriver
最佳答案
您需要将库打包到 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 型号创建虚拟机并在其上安装旧的操作系统版本。
您还需要留意使用 noexec
挂载 /tmp
的 Linux 系统。该设置或某些 SE Linux 设置可能会导致共享对象加载失败。
关于java - 使用 RXTX 部署独立应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57904922/