我用谷歌搜索了一下,但没有找到使用 JNA 从 java 类卸载 dll 的方法。 当我使用 dll 使用此 dll 从 USB 设备传输数据时,我必须从 java 类中卸载我的 dll,以便在不关闭整个程序的情况下重新使用具有相同类的 USB 设备。 这是我如何使用 JNA 加载我的 dll
public interface UsbSensor extends Library {
UsbSensor INSTANCE = (UsbSensor) Native.loadLibrary(
(Platform.isWindows() ? "D:\\UsbDevice.dll" : "D:\\UsbDevice.dll"), UsbSensor.class);
int SearchDevices();
Pointer Startacquisition(String type);
}
然后
UsbSensor sdll = UsbSensor.INSTANCE;
Dll 已加载。这是我如何使用我的功能
sdll.SearchDevices();
sdll.Startacquisition();
现在使用这些函数后,我必须使用上面的代码再次加载 dll 来卸载我的 dll。命令重用这些功能。
那么如何使用JNA动态卸载dll呢?
NativeLibrary.dispose() 应该做你正在寻找的事情。 NativeLibrary 是您正在使用的本机库的 1:1 表示(并且无论如何都由 Native.loadLibrary() 在内部使用)。所以
我遇到了同样的问题,但使用 Native.dispose() 没有帮助。我的问题的解决方案是这个问题和答案。它基本上将本机库的实例设置为 null 并调用垃圾收集器。
您可以创建一个临时类加载器,使用本机函数,清空对类加载器的引用,它将与它加载的类/dll 一起进行 GC
假设您通过
加载了 Java Native LibraryLibrary library = Native.load(name, Library.class, options);
您可以通过
卸载库NativeLibrary nativeLibrary = ((Library.Handler)(java.lang.reflect.Proxy.getInvocationHandler(library))).getNativeLibrary();
nativeLibrary.dispose();
这将立即将文件句柄释放到库(以便您可以删除
.dll
或 .so
)。
如果您将引用清空,库也会被卸载 (
library = null;
)。但是,您无法确定它是否立即卸载。
卸载库的另一种方法(您也可以在此处找到解决方案)是
NativeLibrary nativeLibrary = NativeLibrary.getInstance(name, options);
nativeLibrary.dispose();
其中
name
和 options
与对 Native.load
的调用完全相同。
但是,这种方法有一个问题,可能会导致
dispose
al:失败
要获得正确的实例 (
nativeLibrary
),传递打开库时使用的 options
非常重要。在内部 Native
使用 Map<String, NativeLibrary>
作为缓存,其中密钥由 name + options.toString()
给出。如果此密钥不匹配,NativeLibrary.getInstance
将加载一个新实例,然后将其替换为 dispose
,而不是喜欢处置的实例。
问题是传递给
options
的 Native.load
不是内部用于 NativeLibrary.getInstance
的。 Native.Handler
的实现添加了两个附加选项(如果缺少):
如果
Native.load
中不存在这些选项,则 NativeLibrary.getInstance 会生成不同的密钥来获取库,因此您不会在正确的实例上调用 dispose
。