使用system.loadLibrary()函数加载后立即删除库文件是否可以...?这是场景......
我们正在使用JNI来使用以C语言编写的DomainSocket实用程序来从Java应用程序调用。我们将.SO文件打包在同一个jar中,并使用实用程序在文件系统上创建临时文件,并使用loadLibrary函数加载.SO文件。我们使用File.createTempFile()创建一个唯一的临时文件。我们使用deteleOnExit()在JVM关闭时删除临时文件。
在JVM上的独立应用程序上,这很好用。但是当部署到像Tomcat这样的Web容器时我们遇到了一个问题,因为我们可以在同一个JVM上运行多个应用程序。首先,为部署的每个App创建临时文件。真正的问题是,当应用程序停止并启动或重新部署时,临时文件不会被删除,而是会创建一个新文件。当JVM关闭(Tomcat重新启动)时,将删除所有临时文件。
我们在loadLibrary()之后尝试了删除临时文件的解决方案。这似乎工作正常。重新启动时会创建一个新的临时文件,并在加载后立即删除。
想要检查是否有人有指示/建议?
我们不希望使用common / lib机制每个容器只加载一次.SO文件,因为我们希望将这些.SO文件作为应用程序的一部分。
答案 0 :(得分:1)
使用system.loadLibrary()函数加载库文件后,是否可以删除库文件??
不。操作系统可以自由地卸载"该库随时都可能需要从磁盘重新加载二进制文件。如果你删除了文件(并且它并没有被进程实际保持打开),那么你会得到一些非常奇怪的行为......可能就像一个" BUS ERROR"或其他几乎无法解释的情况。
即使磁带库没有从内存中删除并从磁盘重新加载,各种操作系统都有标记用于"延迟加载"以及其他可能导致您进入竞争条件的情况,您可能会在实际从其中加载所有代码之前删除磁盘库工件。
我们正在使用File.createTempFile()创建一个唯一的临时文件。我们使用deleteOnExit()在JVM关闭时删除临时文件。
这似乎是一种合理的方法,除了您遇到的问题。为什么不在可预测的地方使用可预测的文件名(例如File.createTempFile
),而不是使用/tmp/libgoodstuff.so
?如果您这样做,那么您只需要创建(并安排删除)单个文件(每个要加载的库)。
[我]想检查是否有人有一些指示/建议?
将.so
文件放在应用程序中将很难管理,除非您真正了解目标环境。例如,您需要确保您的目标架构和操作系统正确等等。
最重要的是,作为可分发应用程序的一部分的本机库是Java的痛苦,除非没有其他选项,否则应该避免使用。
答案 1 :(得分:0)
是的,这种方法可能有效,但有一些限制。
调用System.loadLibrary
时,相应的.so
文件将映射到进程地址空间。删除文件后,会立即删除相应的dentry
,但不会删除inode
。也就是说,文件名是未链接的,但文件数据会一直保留,直到最后一次引用该文件为止。
这是包管理器安装更新的方式。即使运行进程使用它们,它们也可能删除可执行文件和共享库。操作系统将确保正在运行的程序继续使用旧版本的库,而新程序将加载新版本。
但是,这种方法不可移植。它适用于Linux,但不适用于其他操作系统,也不适用于所有文件系统(例如,考虑Windows或FAT)。因此,除非您知道正在使用的特定OS平台,否则我不建议这样做。