我正在使用Axis和Apache Tomcat 7编写Web服务。 该服务使用第三方库对文件进行一些转换,最终创建一个包含更多文件(子文件夹和常规文件)的文件夹。转换完成后,服务会创建一个zip存档并将其返回。 当它收到一个新请求时,首先它删除在上一个请求期间创建的文件,并开始处理请求。
服务本身工作正常,至少满足第一个请求。 问题是当收到第二个请求时,服务无法删除上一个请求期间生成的所有文件。 我正在使用Windows XP和Process Explorer,我看到Tomcat保留了一些文件(不是所有文件)都打开了,这就是为什么我无法删除它。
即使服务操作结束,我正在使用的库是否可以保持文件打开? 在我用来创建zip存档的代码中,我似乎关闭了所有打开的流。顺便说一句,即使我原谅关闭它们,在服务操作将结果返回给客户后,它们仍可以保持打开状态吗? 如果是这样,为什么进程Tomcat只保留一些文件?
似乎经过一段时间后某些文件被“释放”,但其他文件始终保持打开状态......
我希望有人可以就如何处理这种情况给我一些建议:)
答案 0 :(得分: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.
}
答案 1 :(得分:0)
好吧,正如我想知道的那样,我正在使用的库并没有关闭所有文件流..
我找到了一种可以在类似情况下使用的解决方法。我发布它,也许有人可以发现它有用或建议我更好的方法来解决问题:)
幸运的是,可以使用java命令从命令行执行jar库,所以我只是用这种方式用Runtime的exec方法执行它:
try {
Process p = Runtime.getRuntime().exec("java -jar library.jar parameters");
p.waitFor();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
通过这种方式,JVM会创建一个新进程,当它死亡时,所有待处理的处理程序都会被重新启动。
如果你不能用java命令执行库,那么这个库可以简单地包装在一个由使用它的简单类所做的自定义jar中,并获取所需的参数。然后可以使用exec()执行包装jar。