垃圾回收的知识点

//: initialization/TerminationCondition.java 
// Using finalize() to detect an object that 
// hasn't been properly cleaned up. 

class Book { 
boolean checkedOut = false; 
Book(boolean checkOut) { 
checkedOut = checkOut; 
} 
void checkIn() { 
checkedOut = false; 
} 
protected void finalize() { 
if(checkedOut) 
System.out.println("Error: checked out"); 
// Normally, you'll also do this: 
// super.finalize(); // Call the base-class version 
} 
} 

public class TerminationCondition { 
public static void main(String[] args) { 
Book novel = new Book(true); 
// Proper cleanup: 
novel.checkIn(); 
// Drop the reference, forget to clean up: 
new Book(true); 
// Force garbage collection & finalization: 
System.gc(); 
} 
} /* Output: 
Error: checked out 
*///:~ 

 
说明:这段程序源自《java编程思想》89页
问题1:输出为什么是“Error: checked out”,在哪里调用了finalize()方法,(因为只有finalize()方法里有打印输出语句System.out.println("Error: checked out");)
问题2:书上说,在main()方法里,由于错误,有一本书(即Book对象)为被check in, 要是没有finalize()来验证终结条件,见很难发现这种缺陷,真是怎么回事
问题3:main()方法是不是调用了两次构造方法,第一次“Book novel = new Book(true);”,第二次new Book


问题1:
finalize()方法是object类中的方法,此方法将在对象被销毁的时候调用,被系统认为是垃圾的对象是没有引用的 既 Book b = new Book();当执行b=null;时,该对象没有任何引用指向它,被系统判断为垃圾,垃圾回收机制是系统自己运行的,但也可手动调用既 System.gc()
问题2:
finalize()方法一般用来释放资源,释放被自己所引用的对象,好让垃圾回收器将没用的对象回收,例如打开了一个文件,当此对象将被销毁的时候就一定要判断是否该文件是否被关闭,否则很容易内存溢出,导致程序崩溃
问题3:
确实调用了辆次构造 第一次有引用指向被新构造出来的对象,第二次没有引用指向它,所以调用System.gc()的时候该对象被销毁,销毁前调用了 finalize()方法打印了那句话



system.gc()应该是垃圾回收函数,就是不用的东西就把它收回去,清理出空间来!但是java中的垃圾是自动回收的,它是根据什么来判断要不要把这个变量或对象当作垃圾回收呢?就是根据一个指针,就是说这个变量或对象系统内没有指针指向他了,就是你再想要用这个变量或对象的时候,系统没有办法找到它了,这样就会把他当作垃圾自动回收!就比如说 例子中的 new Book(true);定义的一个无名称的book对象,这个Book 对象他是存在内存里的,但是你能够找到它并且引用它吗?很明显不可以(因为你找不到一个变量指针指向他,所以无法应用呢)。这时候系统就会把它当垃圾回收掉,这就是java 的回收机制!
问题一:
在system.gc()这个调用时,就把你用new Book(true)定义的无名对象给回收了,但是finalize()这个函数要在这个对象“挂掉”之前执行一下!

问题二:
你的问题我也不知道问的是什么,但是根据我的理解
他说的应该是“这个程序调用system.gc的原意是要回收Novel这个book对象的,但是系统的默认回收了却是用new Book(true)定义的无名对象,这样就达不到原来的意图,万一这个对象占用内存很夸张就会导致“头疼的后果”, 所以他建议每个人在写程序的时候最好加finalize()这个函数,确认下到底有没有回收了自己想要回收的东西,从而保证程序的安全性”

问题三:
是调用了两次构造函数,第二次好像不像对吧,它和第一种用法是一样的,只不过是定义了一个没有名字的对象而已


2.在这段程序中第2次new Book(true);未被checkIn,会输出Error: checked out ,如果没有finalize()来验证,你就不知道第2次的new Book(true);未被checkIn,这就是缺陷。

//

因为垃圾回收站只收垃圾。你用Book nextnovel = new Book(true);
创建对象,它被nextnovel所引用,还有用,在引用没有释放它之前,对象当然不能被清理掉,否则gc()就不是回收垃圾了,而是摧毁所有的对象了。

你在Book nextnovel = new Book(true);之后写一句nextnovel = null;
finalize() 就会被调用了,因为对象不被任何reference所引用,自然是垃圾一件。

另外,gc()只能回收本方法内可见的垃圾,本方法内不可见的,自动回收时间不确定。比如你把上面两句放入一个method中:

void doSth(){
    Book nextnovel = new Book(true);
    nextnovel = null;
}

然后中main中调用doSth(); 再System.gc(); 这时finalize()也不会被调用。

在上面的代码中,new Book(true)肯定就是垃圾,因为它不做任何事情。一般来说,创建对象都要返回给reference,如果象new Book(true);这样直接创建对象而不赋值给任何reference,其目的大致可以分为两种:

1、是为了获得创建对象的“副作用”,这时一般说来对象创建之后就可以扔掉。这个比较简单,不举例了。

2、对象创建后马上把自己注册给了另一个类的静态成员。比如在JDBC中,我们要作的第一件事就是加载Driver类,一般语法如下:
Class.forName("oracle.jdbc.driver.OracleDriver";
也可以这样写:
new oracle.jdbc.driver.OracleDriver();
可以试着在这一句后面加上System.gc(); 你会发现此时gc()没有任何作用,Driver类并不会被清理掉,为什么呢?就是因为它实例化之后就把自己注册给了DriverManager类。

如果你没有用过JDBC,可能对第2点没有什么概念,那么可以看一看下面的例子,单纯的new创建对象之后也不会被回收:

//  Tree.java 
class Leaf{
        static Tree tree; 
        Leaf(Tree t){
                tree = t;
        }
}
        
public class Tree{
        int i = 88;
        Tree(){
                Leaf leaf = new Leaf(this);
        }
        public void finalize() { 
                System.out.println("finalize()"; 
        }
         
        public static void main(String[] args){
                new Tree();
                System.gc();
                System.out.println(Leaf.tree.i);
        }        
}

 

你可以看到,输出是88而不是finalize()。

如你 所说的 直接调用NEW产生的对象 没有引用 所以直接 给垃圾收集器给 收集了
你改动后 产生的引用 只有当引用 与对象 脱钩时 对象才会给收集

一个例子:

//此类说明了 finalize 关键字以及 System.gc() 的作用   
/*   
    finalize 类似 c++中析构函数,表示对象即将消亡时,调用此方法  
    gc() 方法表示把拉级回收器启动,把拉圾收走  
*/  
  
class Person {   
       
    private String name;   
    private int age;   
       
    public Person() {   
    }   
    public Person(String name) {   
        this.name = name;      
    }   
    public Person(String name,int age) {   
        this(name);     
        this.age = age;   
    }   
       
    //每个类里面都有finalize方法,和构造方法功能相反,一个是对象产生时调用,一个是对象消亡时调用   
    public void finalize() {   
           
        System.out.println("开始清理对象...");   
    }   
       
    public static void main(String[] args) {   
        //下面三个对象一产生即成为拉圾   
        new Person();   
        new Person();   
        new Person();   
           
        //如果不加上下面这句,以上产生的三个对象虽成为拉圾,但不一定马上就会启用拉圾回收机制把拉圾回收走   
        //所以就可能看不到 finalize 方法内部执行的效果   
        System.gc();   
    }   
       
}  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值