Java 加载到JVM后删除临时文件

Java 加载到JVM后删除临时文件,java,tomcat,jvm,java-native-interface,Java,Tomcat,Jvm,Java Native Interface,使用system.loadLibrary()函数加载库文件后立即删除它可以吗。。。?下面是一个场景 我们使用JNI使用C语言编写的DomainSocket实用程序从Java应用程序调用。我们将.SO文件打包在同一个jar中,并使用实用程序在文件系统上创建一个临时文件,然后使用loadLibrary函数加载.SO。我们正在使用File.createTempFile()创建一个唯一的临时文件。我们使用deteleOnExit()在JVM关闭时删除临时文件 在JVM上的独立应用程序上,这很好。但是,当

使用system.loadLibrary()函数加载库文件后立即删除它可以吗。。。?下面是一个场景

我们使用JNI使用C语言编写的DomainSocket实用程序从Java应用程序调用。我们将.SO文件打包在同一个jar中,并使用实用程序在文件系统上创建一个临时文件,然后使用loadLibrary函数加载.SO。我们正在使用File.createTempFile()创建一个唯一的临时文件。我们使用deteleOnExit()在JVM关闭时删除临时文件

在JVM上的独立应用程序上,这很好。但是,当部署到Tomcat这样的web容器时,我们会遇到一个问题,因为我们可以在同一个JVM上运行多个应用程序。首先,为部署的每个应用程序创建一个临时文件。真正的问题是,当应用程序停止、启动或重新部署时,临时文件不会被删除,而是创建了一个新的临时文件。JVM关闭(Tomcat重新启动)时,所有临时文件都将被删除

我们尝试了一种在loadLibrary()之后删除临时文件的解决方案。这似乎效果不错。重新启动时会创建一个新的临时文件,并在加载后立即删除

想看看有没有人有什么建议

我们不希望使用common/lib机制在每个容器中只加载一次.SO文件,因为我们希望这些.SO文件成为应用程序的一部分

使用system.loadLibrary()函数加载库文件后立即删除它可以吗

没有。操作系统可以随时“卸载”库,并且可能需要从磁盘重新加载二进制文件。如果删除该文件(并且该进程实际上没有打开该文件),则会出现一些非常奇怪的行为。。可能是“总线错误”或其他难以解释的情况

即使库没有从内存中删除并从磁盘重新加载,各种操作系统都有“延迟加载”的标志,以及其他可能使您进入竞争条件的情况,您可能会在从磁盘上实际加载所有代码之前删除磁盘库工件

我们正在使用File.createTempFile()创建一个唯一的临时文件。我们使用deleteOnExit()在JVM关闭时删除临时文件

这似乎是一个合理的方法,除了你遇到的问题。与其使用
File.createTempFile
,为什么不在可预测的位置使用可预测的文件名(例如
/tmp/libgoodstuff.so
)?如果这样做,则只需创建(并计划删除)单个文件(每个要加载的库)

[一] 想看看有没有人有什么建议

在应用程序中放置
.so
文件将很难管理,除非您确实非常了解您的目标环境。例如,您需要确保您的目标体系结构和操作系统是正确的,等等


归根结底,本机库作为可分发应用程序的一部分是Java的一大难题,除非没有其他选择,否则应该避免使用。

是的,这种方法可能有效,但有一定的限制

调用
System.loadLibrary
时,相应的
。因此
文件被映射到进程地址空间。删除文件时,会立即删除相应的
dentry
,但不会删除
inode
。也就是说,文件名被取消链接,但文件数据会一直保留,直到释放对文件的最后一次引用

这是软件包管理器安装更新的方式。它们可能会删除可执行文件和共享库,即使它们被正在运行的进程使用。操作系统将确保正在运行的程序继续使用旧版本的库,而新程序将加载新版本


然而,这种方法是不可移植的。它可以在Linux上工作,但不能在其他操作系统上工作,也不能在每个文件系统上工作(例如,考虑Windows或FAT)。因此,除非您知道正在使用的特定操作系统平台,否则我不建议您这样做。

当您说可以随时卸载库时,您指的是什么操作系统?@apangin我没有想到具体的操作系统。但是没有POXIX等要求代码保持加载状态,因此基于磁盘的工件可以自由消失。我认为“未定义行为”是加载后从磁盘上删除共享库的结果。我不知道删除共享库时会导致应用程序崩溃的操作系统(至少是Oracle JDK支持的操作系统)。通常操作系统要么拒绝删除(Windows),要么只是取消文件名的链接(Linux),将文件数据保存在磁盘上。删除该文件不会影响已打开的该文件的内存映射。我们在web容器中仅使用一个.SO文件就遇到了一个问题。由于classloader的原因,一个Web应用加载的.SO文件无法由另一个Web应用加载。Tomact为每个webapp分配一个唯一的类加载器,并多次加载相同的类加载器。因此将不起作用…@user2089210对,我错过了这一部分。因此,如果不需要跨平台移植应用程序,那么可以在加载库后立即删除它们。嗯,拥有JNI库会使应用程序无论如何都不可移植。