在Java程序的生命周期中,Java运行环境提供了一个系统的垃圾回收器线程,负责自动回收那些没有被引用的对象所占用的内存,这种清除无用对象进行内存回收的过程就叫作垃圾回收 (garbage collection)。Java提供自动内存回收的功能,可以让程序员减轻许多内存管理的负担,同时也减少犯错的机会。
当一个对象被创建时,JVM会为该对象分配一定的内存、调用该对象的构造方法并开始跟踪该对象。当该对象停止使用时,JVM将通过垃圾回收器回收该对象所占用的内存。那Java是如何知道一个对象是无用的呢?
这是因为系统中的任何对象都有一个引用计数器,一个对象被引用1次,则该对象的引用计数器为1,被引用2次,则引用计数器为2;相反,若对一个对象减少1次引用,则该对象的引用计数器就减1,依次类推,当一个对象的引用计数器减到0时,说明该对象可以回收。
垃圾回收的好处:
- 它把程序员从复杂的内存追踪、监测、释放等工作中解放出来。
- 它防止了系统内存被非法释放,从而使系统更加稳定。
垃圾回收的特点:
(1)只有当一个对象不被任何引用类型的变量使用时,它占用的内存才可能被垃圾回收器回收。
如下面的程序段:
String str1="This is a string";
String str2 = str1;
str1 = null;
str2 = new String("This is another string");
当程序执行到第3行时,“This is a string” 对象仍然被 str2 引用,因此,此时不能被垃圾回收器回收。当程序执行完第4行,str2 引用了一个新的字符串对象,此时"This is a string"对象不在被任何引用类型的变量(str1和str2)引用,此时该对象可以被当作垃圾回收。
(2)不能通过程序强迫垃圾回收器立即执行
垃圾回收器负责释放没有引用与之关联的对象所占用的内存,但是回收的时间对程序员是透明的,在任何时候,程序员都不能通过程序强迫垃圾回收器立即执行,但可以通过调用System.gc() 或者Runtime.gc() 方法提示垃圾回器进行内存回收操作,不过这也不能保证调用该方法后,垃圾回收器立即执行。
(3)当垃圾回收器将要释放无用对象占用的内存时,先调用该对象的 finalize() 方法。
在Java语言中对象的回收是由系统进行的,但有一些任务需要在回收时进行,如清理一些非内存资源、关闭打开的文件等。这可通过覆盖对象中的finalize() 方法来实现,因为系统在回收时会自动调用对象的finalize() 方法。
finalize() 方法的形式如下:
protected void finalize()throws Throwable
由于只有当垃圾回收器将要释放该对象的内存时,才会执行该对象的finalize() 方法,如果在程序退出之前,垃圾回收器始终没有执行释放内存的操作,那么垃圾回收器将不会调用无用对象的finalize() 方法。换句话说,假如一个程序只占用了少量的内存,没有造成严重的内存需求,于是垃圾回收器没有释放这些对象的内存就退出了。
显然,如果程序员为某个对象定义了finalize() 方法,JVM可能不会调用它,因为垃圾回收器不曾释放过这个对象的内存,调用System.gc() 也不会起作用,因为它仅仅是给JVM一个建议而不是命令。当一个对象将要退出生命周期时,可以通过finalize() 方法来释放对象所占的其他相关资源,但是,JVM有很大的可能不调用对象的finalize() 方法,因此很难保证使用该方法来释放资源是安全有效的。
感谢大家的耐心阅读,如有建议请私信或评论留言
|