FTP服务:file.delete()与file.deleteOnExit()

 file.delete()file.deleteOnExit()

之前使用ftp下载文件的时候会用到File.createTempFil()创建临时文件存储数据,用完之后就用file.delete()与file.deleteOnExit()删除临时文件。在windows的开发环境进行测试时,临时文件会被创建在C:Users{当前电脑用户名}AppDataLocalTemp该目录下。在现场环境,临时文件则会被创建在tomcat的temp文件夹下面。最近发现现场环境中temp下面居然堆积了大量的临时文件,然后查了一下代码发现是因为用了file.deleteOnExit()

这里得介绍一下file.delete()file.deleteOnExit()这两个删除文件方法:

file.delete() :删除文件,删除的是创建File对象时指定与之关联创建的那个文件.这是一个立刻执行的操作

file.deleteOnExit() : JVM进程退出的时候删除文件,通常用在临时文件的删除.这个不会立刻执行,会等到jvm进程退出的时候删除

这里看到一个”JVM进程退出”,这是什么意思呢?百度一下得到:

JVM的关闭意味着将停止系统中所有的任务

按照这里的介绍,当应用关闭的时候,应该就可以把临时文件删了。然而,现场环境还是存了一大堆的临时文件没有删除。

这时候查看一下源码:

File.java

 1 public void deleteOnExit() {
 2     SecurityManager security = System.getSecurityManager();
 3     if (security != null) {
 4         security.checkDelete(path);
 5     }
 6     if (isInvalid()) {
 7         return;
 8     }
 9     DeleteOnExitHook.add(path);
10 }

DeleteOnExitHook.java

 1 package java.io;
 2 import java.util.*;
 3 import java.io.File;
 4 
 5 /**
 6  * This class holds a set of filenames to be deleted on VM exit through a shutdown hook.
 7  * A set is used both to prevent double-insertion of the same file as well as offer
 8  * quick removal.
 9  */
10 
11 class DeleteOnExitHook {
12     private static LinkedHashSet<String> files = new LinkedHashSet<>();
13     static {
14         // DeleteOnExitHook must be the last shutdown hook to be invoked.
15         // Application shutdown hooks may add the first file to the
16         // delete on exit list and cause the DeleteOnExitHook to be
17         // registered during shutdown in progress. So set the
18         // registerShutdownInProgress parameter to true.
19         sun.misc.SharedSecrets.getJavaLangAccess()
20             .registerShutdownHook(2 /* Shutdown hook invocation order */,
21                 true /* register even if shutdown in progress */,
22                 new Runnable() {
23                     public void run() {
24                        runHooks();
25                     }
26                 }
27         );
28     }
29 
30     private DeleteOnExitHook() {}
31 
32     static synchronized void add(String file) {
33         if(files == null) {
34             // DeleteOnExitHook is running. Too late to add a file
35             throw new IllegalStateException("Shutdown in progress");
36         }
37 
38         files.add(file);
39     }
40 
41     static void runHooks() {
42         LinkedHashSet<String> theFiles;
43 
44         synchronized (DeleteOnExitHook.class) {
45             theFiles = files;
46             files = null;
47         }
48 
49         ArrayList<String> toBeDeleted = new ArrayList<>(theFiles);
50 
51         // reverse the list to maintain previous jdk deletion order.
52         // Last in first deleted.
53         Collections.reverse(toBeDeleted);
54         for (String filename : toBeDeleted) {
55             (new File(filename)).delete();
56         }
57     }
58 }

可以看出,使用deleteOnExit方法的话不会立刻删除,而是把文件地址先保存到一个链表中。ShutdownHook正常结束的话,就会把之前存的文件地址拿出来一个一个的删掉。如果异常结束的话,那么这些临时文件就删除不了了。

因此推断,现场环境的临时文件垃圾,是因为平时关闭应用是直接关闭窗口导致异常结束引起的。

值得一提的是,这样使用deleteOnExit方法的话会占用大量的内存,直至JVM终止,因此建议谨慎使用。

参考文章:

http://www.hackerav.com/?post=80616

https://blog.csdn.net/qq_44813090/article/details/104227356

原文地址:https://www.cnblogs.com/bestlmc/p/12370755.html