0

我正在使用 Axis 和 Apache Tomcat 7 编写一个 Web 服务。该服务使用第三方库对文件进行一些转换,并最终创建一个包含更多文件(子文件夹和常规文件)的文件夹。转换完成后,该服务会创建一个 zip 存档并将其返回。当它收到一个新请求时,首先它会删除在最后一个请求期间创建的文件并开始处理该请求。

服务本身运行良好,至少第一个请求得到了满足。问题是当收到第二个请求时,服务无法删除最后一个请求期间生成的所有文件。我使用的是 Windows XP 和 Process Explorer,我看到 Tomcat 保持一些文件(不是所有文件)打开,这就是我无法删除它的原因。

即使服务操作结束,我正在使用的库是否可能使文件保持打开状态?在我用来创建 zip 存档的代码中,我似乎关闭了所有打开的流。顺便说一句,即使我原谅关闭它们,在服务操作将结果返回给客户后它们还能保持打开状态吗?如果是这样,为什么 Tomcat 进程只打开一些文件?

似乎一段时间后,某个文件被“释放”,但其他文件始终保持打开状态......

我希望有人能给我一些关于如何处理这种情况的建议:)

4

2 回答 2

1

重新发布我的评论,这似乎很有用。

如果一个文件处理程序没有被释放,它永远不会被释放,直到 servlet 容器关闭。一些实现还可能将文件处理程序的释放延迟到对象被垃圾收集时。除了确保关闭所有处理程序之外,您无能为力。如果是第三方库,那么您必须报告错误或自行修复。

我防止此类问题的最佳做法是确保文件处理程序以与打开它相同的方法关闭。如果它没有以该方法打开,则永远不要关闭它。

public void method() {
    //open file handler
    //do something
    //close file handler. make sure it is closed even if there is an exception.
}

并且永远不要让文件处理程序成为一个字段。

public class A {
    private FileInputStream fin = null; // never do this. you will have hard time keeping track of when to release it.
}
于 2012-05-28T15:28:31.403 回答
0

好吧,正如我想知道的那样,我正在使用的库并没有关闭所有文件流..

我找到了一种可以在类似情况下使用的解决方法。我发布它,也许有人会发现它有用或建议我更好的方法来解决问题:)

幸运的是 jar 库可以使用 java 命令从命令行执行,所以我只是用 Runtime 的 exec 方法以这种方式执行它:

try {   
    Process p = Runtime.getRuntime().exec("java -jar library.jar parameters");
p.waitFor();
} catch (InterruptedException | IOException e) {
    e.printStackTrace();
}

以这种方式,JVM 创建了一个新进程,当它死亡时,所有挂起的处理程序都将被释放。

如果您无法使用 java 命令执行该库,则可以将此类库简单地包装在一个自定义 jar 中,该 jar 由一个使用它并获取所需参数的简单类制作。然后可以使用 exec() 执行包装 jar。

于 2012-05-29T09:16:37.230 回答