当我同时多次执行构建的 JAR 时,在 Java 中加载 OpenCV DLL 库时遇到问题。我得到的错误如下:
Caused by: java.lang.UnsatisfiedLinkError: Can't load library: C:\Users\xxx\AppData\Local\Temp\opencv_openpnp15738695246714582909
u\pattern\opencv\windows\x86_64\opencv_java320.dll
该异常发生在除一个 JAR 执行之外的所有 JAR 执行中。一个总是工作得很好。如果我一个接一个地执行 JAR,一切都会正常,但我需要同时执行它们(由于其他原因)。
我使用 Java 17 和 Maven org.openpnp.opencv 4.9.0,但在 OpenCV 3.2.0 上遇到相同的错误。 JAR 在 Windows 主机上执行。在代码中,我按如下方式加载库:
static {
nu.pattern.OpenCV.loadLocally();
}
我尝试阅读一些源代码,我认为问题在于,如果操作系统是 Windows,OpenCV loadLocally() 方法会在启动时删除所有其他临时 DLL,因此在加载其他 JAR 执行之前删除了其他 JAR 执行的 DLL ,但错误发生后文件夹仍在 tmp 目录中(但其中没有 DLL 文件)。
OpenCV 代码:
if (OS.WINDOWS.equals(os)) {
destination = new TemporaryDirectory().deleteOldInstancesOnStart().getPath().resolve("./" + location).normalize();
} else {
destination = new TemporaryDirectory().markDeleteOnExit().getPath().resolve("./" + location).normalize();
}
有什么建议可以解决这个问题吗?或者还有其他方法可以正确执行此操作吗?
更新: 我通过将 DLL 文件从类路径复制到 tmp 目录并通过 System.load() 手动加载它来使其工作,但这样 DLL 文件将永远不会被删除并最终炸毁文件系统。有没有办法在 JVM 关闭后干净地删除这些文件?在 Linux 上,您可以使用关闭挂钩来执行此操作,但在 Windows 上,这不起作用,因为 DLL 文件以某种方式被锁定。
您可以尝试使用 opencv-platform 而不是直接使用 opencv,因为它带有本机库。您可以轻松地在线获取其 jar 文件,或者如果您正在使用 Maven,则其依赖项存在于 Maven 中央存储库中。对于 Maven,您可以在 pom.xml 中添加此依赖项
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv-platform</artifactId>
<version>4.9.0-1.5.10</version>
</dependency>
我刚刚想出了一个简单的方法。您可以将每个执行传递给自定义 tmp 目录。然后,OpenCV 仅删除当前执行的 tmp 目录中的 DLL 文件。我不知道我怎么没有早点得到这个,但这应该是这个问题的一个简单的解决方案。