class Person{
private String name;
private int age;
public Person(String name,int age){
   this.name=name;
   this.age=age;

}
public String toString(){
   return "姓名" +this.name+"年龄"+this.age;

}
public void finalize() throws Throwable{
System.out.println(this);

}

}public class SystemDemo { public static void main(String[] args) {
Person per=new Person("好样的",20);
per=null;

System.gc();
System.out.println("好样的");//1
}}上面的程序是测试finalize()方法,在main()方法中实例化对象后又强制断开,当直接调用JVM回收垃圾时,如果去掉//1,
finalize()方法不会输出,而增加//1后,就能输出toString()的返回值了,这是为什么????

解决方案 »

  1.   

    因为调用gc方法,jvm不一定真的去回收对象
      

  2.   

    我运行程序时,不管有没有"//1”,输出结果都是 :
    好样的
    姓名好样的年龄20
    因为:System.gc();是运行垃圾回收器垃圾回收器,可是JVM调用finalize() 是不定时的,即使你用System.gc();通知JVM让回收垃圾,但它不一定马上调用,具体是么时候调用垃圾回收机制,那由JVM决定,是不定时的,也与java的运行环境有关系。
      

  3.   

    System.out.println("好样的");我把这句删掉之后,finalize()也不会被调用?
    增加这句输出的,finalize()也会被调用,JVM怎样判定调用finalize()方法的??
      

  4.   

    调用GC只是给虚拟机一个建议去回收。真正什么时候回收。是由JVM自己判定的。
      

  5.   

    调用finalize()方法 回收机制是jvm自身判断的是否要调用 没有固定的顺序和时间
      

  6.   

    没有1的时候JVM知道你后面没别的语句了,,可能直接忽略了System.gc的建议不运行GC算法了,大多情况下System.gc会让JVM进行GC,它仅仅是给JVM一个建议,让JVM尽力去运行GC算法。在我的机器上,System.gc()让引起JVM做Full GC,也就是对整个堆(YoungGen、OldGen、PermGen)都运行GC,严重影响了效率
      

  7.   

    。。楼主难道不会把代码嵌到格式里吗?这跟//1没有关系在根搜索算法中不可达到的对象,也并非是“一定会死的”,真正宣告一个对象死亡至少要经历两次标记过程:如果在进行一遍跟搜索后,发现一个对象没有引用链与其连接并且编译器认为是有必要执行finalize()方法(没有覆盖finalize()或者finalize已经被执行过,则认为“没有必要执行”),这个对象就被标记一次。finalize()是最后一次机会拯救这个对象不被回收的机会。如果在finalize方法内此对象被引用,那么就不会被回收,否则....这是内存回收的原理,至于什么时候执行finalize(),可以这么理解:当这个对象第一次被标记之后,JVM会把这个对象加入一个名为F-Queue的队列中,并在稍后由一条由虚拟机自动建立的,低优先级的Finalizer线程去执行,由于优先级比较低,所以不能保证等待它执行结束。所有有的时候就执行不到finalize()咯你可以这样修改一下main()方法:public static void main(String[] args) {
    Person per=new Person("好样的",20);
    per=null;System.gc();//第一次标记,把new Person("好样的",20)这个对象加入F-Queue队列中
    System.out.println("好样的");//1
    try{
    Thread.sleep(500);//因为Finalizer线程优先级低,所以让主线程等它0.5秒
    }catch(InterruptedException e){
    }
    System.gc();//第二次标记,没有引用,删掉此对象
    }