package com.test;
public class Son {
static boolean isgcrun=false;
static boolean flag=false;
static int created=0;
static int finalized=0;
int i;
public Son(){
i=++created;
if(i==100){
System.out.println("i have 100 sons");
}
}
protected void finalize() throws Throwable {
if(!isgcrun){
isgcrun = true;
System.out.println("gc kill sons...start!!!,"+ i + " sons killed ");
}
if(i==100){
System.out.println("-------set flag!!!---don't kill son!!!----");
flag = true;
}
finalized ++ ;
if(finalized >= created){
System.out.println("all killed!!!");
}
}
}
package com.test;
public class Father {
public static void main(String[] args) {
while(!Son.flag){
new Son();
new String("站岗中。。。。");
}
System.out.println( "After all son have been created:/n"+
"total created ="+Son.created+
",total finalized ="+Son.finalized);
System.out.println("gc():");
System.gc();
System.out.println("runFinalization():");
System.runFinalization();
System.out.println("bye");
}
}
运行结果:
i have 100 sons
gc kill sons...start!!!,4544 sons killed
-------set flag!!!---don't kill son!!!----
After all son have been created:
total created =47649,total finalized =30257
gc():
runFinalization():
all killed!!!
bye
分析:
在一个循环当中创建对象,并且只是创建,而不引用,也就是说这个对象会自动的被系统当作垃圾处理掉。
但请注意,finalize()方法并不是立刻就会执行的,执行的时间完全由系统来决定。
所以很有可能的情况是已经创建了20000个对象,才开始其中的某一个对象的清除工作(这可能和时间或者系统内容的占用有关)。
为什么会被自动被系统当作垃圾回收?系统什么时候开始回收?
我们从jvm的gc顺序中可以分析得到答案
A. JVM会试图为相关Java对象在Eden中初始化一块内存区域(所有新对象不断的创建,并放在Eden中,使得Eden不断膨胀)
B. 当Eden空间足够时,内存申请结束。否则到下一步(对象太多,内存资源开始不足)
C. JVM试图释放在Eden中所有不活跃的对象(没有任何引用的对象为不活跃对象,判断原则;系统将会决定在这个时候回收掉这个对象)
引:不活跃对象判断原则(http://hi.baidu.com/jieriw/blog/item/6f690f32f793e6cda3cc2bd5.html)
应用阶段:即该对象至少有一个引用在维护他.
不可视阶段:即超出该变量的作用域。这里有一个很好的做法,因为JVM在GC的时候并不是马上进行回收,而是要判断对象是否被其他引用在维护.所以,这个时候如果我们在使用完一个对象以后对其obj=null或者obj.doSomething()操作,将其标记为空,可以帮助JVM及时发现这个垃圾对象.
不可到达阶段:就是在JVM中找不到对该对象的直接或者间接的引用。
可收集阶段,终结阶段,释放阶段:此为回收器发现该对象不可到达,finalize方法已经被执行,或者对象空间已被重用的时候。
我们从这可以发现垃圾回收过程往往都会迟一点才开始,如果有足够的时间gc还是能把这些没用的对象都回收了(让线程wait一会就能看到了),这也是为啥我们都选择在finally中进行文件流之类的关闭操作,因为finalize可靠了,母猪都会爬树了(当然现在母猪也有可能会爬树了);
另外对于finalize的不可靠,Java 1.1 通过提供一个Runtime.runFinalizersOnExit()方法部分地解决了这个问题(现在使用Runtime.exit())。Runtime.exit() 方法并不立即试图启动垃圾回收器。而是当应用程序退出时,它调用每个对象的finalize()方法。
正如你可能猜测的那样,通过调用Runtime.exit()方法强制垃圾回收器清除所有独立对象的内存,当清除代码执行时也可能引起明显的延迟。
文章出处:http://www.dxmath.com/