在我们使用system.loadlibrary()函数加载库文件后立即删除它可以吗。。。?以下是场景。。。
我们使用jni来使用用c语言编写的domainsocket实用程序从java应用程序调用。我们将.so文件打包在同一个jar中,并使用实用程序在文件系统上创建一个临时文件,然后使用loadlibrary函数加载.so。我们正在使用file.createtempfile()来创建一个唯一的临时文件。我们正在使用deteleonexit()删除jvm关闭时的临时文件。
在jvm上的一个独立应用程序上,这可以正常工作。但是我们在部署到像tomcat这样的web容器时遇到了一个问题,因为我们可以在同一个jvm上运行多个应用程序。首先为部署的每个应用程序创建一个临时文件。真正的问题是,当应用程序停止、启动或重新部署时,临时文件不会被删除,而是创建了一个新的临时文件。当jvm关闭(tomcat重启)时,所有temp文件都会被删除。
我们尝试了一种在loadlibrary()之后删除temp文件的解决方案。这似乎很管用。重新启动时会创建一个新的临时文件,并在加载后立即删除。
想看看有没有人有什么建议?
我们不希望使用common/lib机制在每个容器中只加载一次.so文件,因为我们希望使这些.so文件成为应用程序的一部分。
2条答案
按热度按时间nom7f22z1#
在我们使用system.loadlibrary()函数加载库文件后立即删除它可以吗。。。?
不。操作系统可以随时“卸载”库,可能需要从磁盘重新加载二进制文件。如果你删除了这个文件(实际上它并没有被进程打开),那么你会得到一些非常奇怪的行为。。可能是“总线错误”或其他难以解释的情况。
即使库没有从内存中删除并从磁盘重新加载,各种操作系统都有“延迟加载”的标志,以及其他一些可能会使您陷入竞争状态的标志,您可能会在所有代码实际从磁盘上加载之前删除磁盘库工件。
我们正在使用file.createtempfile()来创建一个唯一的临时文件。我们使用deleteonexit()在jvm关闭时删除临时文件。
这似乎是一个合理的方法,除了你遇到的问题。而不是使用
File.createTempFile
,为什么不在可预测的位置使用可预测的文件名(例如/tmp/libgoodstuff.so
)? 如果这样做,则只需创建(并计划删除)单个文件(每个要加载的库)。[i] 想看看有没有人有什么建议?
放置
.so
除非您非常了解目标环境,否则应用程序中的文件将很难管理。例如,您需要确保您的目标体系结构和操作系统是正确的,等等。归根结底,本机库作为可分发应用程序的一部分是java的一大难题,除非没有其他选择,否则应该避免。
xa9qqrwz2#
是的,这种方法可能有效,但有一定的限制。
什么时候
System.loadLibrary
被称为,对应的.so
文件被Map到进程地址空间。删除文件时,相应的dentry
立即移除,但不是inode
. 也就是说,文件名被取消链接,但文件数据被保留,直到释放对文件的最后一个引用。这就是包管理器安装更新的方式。它们可以删除可执行文件和共享库,即使它们被正在运行的进程使用。操作系统将确保正在运行的程序继续使用旧版本的库,而新程序将加载新版本。
然而,这种方法是不可移植的。它可以在linux上工作,但不能在其他操作系统上工作,也不能在每个文件系统上工作(例如,考虑windows或fat)。因此,除非您了解所使用的特定操作系统平台,否则我不建议这样做。