我有一个现有的应用程序,该应用程序通常可以通过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
答案 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设置可能会导致共享对象加载失败。