Java 用于加载系统库时,无法删除临时文件
我试图通过将jar文件中的.DLL复制到临时文件,然后加载该文件,将本机库加载到系统中:Java 用于加载系统库时,无法删除临时文件,java,dll,Java,Dll,我试图通过将jar文件中的.DLL复制到临时文件,然后加载该文件,将本机库加载到系统中: try (InputStream in = getResourceStream("/lib/Foo.dll")) { File file = createTemporaryFileFromStream(in); System.load(file.getAbsolutePath()); if (!file.delete()) { System.err.println("Failed to
try (InputStream in = getResourceStream("/lib/Foo.dll")) {
File file = createTemporaryFileFromStream(in);
System.load(file.getAbsolutePath());
if (!file.delete()) {
System.err.println("Failed to delete temporary file " + file.getAbsolutePath());
}
}
但是file.delete()调用失败,我只剩下一个临时文件
如果删除System.load(…)调用,则可以删除临时文件,因此System.load(…)似乎会保持文件资源处于打开状态,从而阻止文件删除工作(这是在Windows 7 64位计算机上)
我还添加了一个file.deleteOnExit()调用,但JVM关闭后临时文件仍然保留
我还添加了一个自定义关机挂钩,以防万一:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
if (file.exists()) {
if (!file.delete()) {
System.err.println("Shutdown failed to delete file " + file.getAbsolutePath());
}
}
}
});
同样,临时文件没有被删除
我确实希望从jar文件加载.DLL,而不是修改java.library.path系统属性并指向.DLL的绝对位置,尽管上面的代码实际上是从jar文件资源加载.DLL,但它会留下一个临时文件,这是不可接受的
是否有一种方法可以使用在加载库后可以删除的临时文件来执行此操作 可能重复感谢卸载DLL的信息。我会调查的。虽然该解决方案依赖于调用System.gc(),但它不保证在调用(IIRC)时实际执行任何内存清理,因此FileOutputStream中保存的文件描述符可能并不总是被释放。我按照建议添加了一个自定义类装入器,并在清空类装入器和装入的类后运行垃圾收集器。如果没有System.load()调用,我可以看到在这些对象上调用终结器。但是,当存在System.load()调用时,在垃圾收集期间不会调用终结器。嗯,可能DLL代码没有正确地释放对象引用。我将尝试另一个.DLL,看看会发生什么。。。