file.delete()与file.deleteOnExit()
之前使用ftp下载文件的时候会用到File.createTempFil()创建临时文件存储数据,用完之后就用file.delete()与file.deleteOnExit()删除临时文件。在windows的开发环境进行测试时,临时文件会被创建在C:\Users\{当前电脑用户名}\AppData\Local\Temp该目录下。在现场环境,临时文件则会被创建在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