前两天项目中碰到一个功能,简单点说就是:
1、在线上传zip文件。
2、解压出里面的文件。
3、解析里面的xml文档。
4、将数据存储到对应的数据表中。
5、以上数据存储完成以后删除目录下的所有文件。
6、当任何一处报错以后,删除已经存储的数据。
以上是导入功能,同样还有导出功能,就是上面的需求反转过来,这个没什么特别的。这两个功能从设计到完善花费了我两天时间,功能实现没什么难度,但是过程中遇到了点有意思的东西,在这里先记录一下,免得忘记。
其实开始的时候是没有想过要在存储数据完成或者导出数据完成以后删除目录文件的,因为项目重启的时候项目目录下的其余文件直接自动就删除掉了。但是因为zip文件导入最大的限制是五十兆,多操作几次容量还是挺可怕,本身服务器提供给项目的容量并不会很大。但是就是做这个删除功能的时候让我遇到了一个问题,问题很小,但是也让我很疑惑。
以上是废话,是给我自己看的,可以无视。
首先我写了个迭代删除文件的工具类,这个在本地测试时完全没有问题的,但是放在项目中就不起作用。开始我想到的是项目路径是不是有权限保护,无法删除,但是经过测试后发现不是这个原因。然后我想到的原因肯定是文件被占用了,应该是文件的流对象没有关闭。于是我先关闭流对象再删除,果然zip文件删除了,但是xml文档却没有删除,手动删除发现是jvm对她们占用。我想应该是解析xml的对象还存在没有被收回,但是这个问题难到我了,流可以关闭,解析的对象我没办法主动收回啊。我试着将对象置为null、没有效果。同时我又在后面加上System.gc();发现居然可以删除了。这就让我很奇怪了,因为我们都知道gc()是不能手动启动的,我们只能调用,能不能触发还得看它老人家的心情。所以我就想着做个小测试。废话不多说上代码:
package 垃圾回收;
public class GcTest {
public static void main(String[] args) {
Gc c1 = new Gc();
Gc c2 = new Gc();
Gc c3 = new Gc();
Gc c4 = new Gc();
Gc c5 = new Gc();
System.gc();
}
}
class Gc{
static int i;
private int j;
public Gc(){
j=++i;
System.out.println("构造函数"+i);
}
public void finalize(){
System.out.println("finalize"+j);
}
}
输出结果:
构造函数1
构造函数2
构造函数3
构造函数4
构造函数5
说明创建的五个对象都没有被回收。
然后我们将对象置空再试试:
package 垃圾回收;
public class GcTest {
public static void main(String[] args) {
Gc c1 = new Gc();
Gc c2 = new Gc();
Gc c3 = new Gc();
Gc c4 = new Gc();
Gc c5 = new Gc();
c3=null;
c4=null;
c5=null;
System.gc();
}
}
class Gc{
static int i;
private int j;
public Gc(){
j=++i;
System.out.println("构造函数"+i);
}
public void finalize(){
System.out.println("finalize"+j);
}
}
输出结果:
构造函数1
构造函数2
构造函数3
构造函数4
构造函数5
finalize5
finalize4
finalize3
说明置空的对象都已经被回收了。
这给我的感觉并不是网上查的那样随机,暂时记录一下,以便验证。