關于Java垃圾回收問題
Java垃圾回收器只知道釋放那些經由new分配的內存,所以它不知道該如何釋放該對象的這塊"特殊"內存.為了應對這種情況,Java允許在類中定義一個名為finalize()的方法.它的工作原理"假定"是這樣的:一旦Java垃圾回收器準備好釋放對象占用的存儲空間,將首先調用其finalize()方法.并且在下一次垃圾回收動作發生時,才會真正回收對象占用的內存.所以要是你打算用finalize(),就能在垃圾回收時刻做一些重要的清理工作.也許你會發現,只要程序沒有瀕臨豐儲空間用完的那一刻,對象占用的空間就總也得不到釋放,如果程序執行結束,并且垃圾回收器一直沒有釋放你創建的任何對象的存儲空間,則隨著程序的退出,那些資源也會全部交還給操作系統.
這個策略是恰當的,因為垃圾回收本身也有開銷,要是不使用它,那就不用支付這部分開銷.所以你根本沒有辦法知道垃圾回收器會不會執行,什么時候執行.你要回收的對象不一定會被回收.finalize()方法用于清理什么樣的對象?如果我要清理某個對象,而該對象中含有其它對象,finalize()就應該明確釋放那些對象呢?
不----無論對象是如何創建的,Java垃圾回收器都會負責釋放對象占據的所有內存.這就將對finalize()的需求限制到一種特殊情況,即通過某種創建對象方式以外的方式為對象分配存儲空間.不過,大家也看到,Java中一切皆為對象,那這種特殊情況是怎么回事?看來之所以要有finalize(),是由于在分配內存時可能采用了類似C語言中的做法.而非Java中的通常做法.
這種情況主要發生在使用"本地方法"的情況下,本地方法是一種在Java中調用非Java代碼的方式.本地方法目前只支持C和C++,但它們可以調用其他語言寫的代碼,所以實際上可以調用任何代碼.在非Java代碼中,也許會調用C的malloc()函數系列來分配存儲空間,而且除非調用了free()函數,否則存儲空間將得不到釋放,從而造成內存泄露.當然,free()是C和C++中的函數,所以要在finalize()中用本地方法調用它.至此,大家或許明白了不要過多地使用finalize()的道理了.System.gc(),強行運行垃圾回收器.
finalize()在什么時候被調用?有三種情況1.對象被Garbage Collection時自動調用,比如運行System.gc()的時候.2.程序退出時為每個對象調用一次finalize方法。3.顯式的調用finalize方法
除此以外,正常情況下,當某個對象被系統收集為無用信息的時候,finalize()將被自動調用,但是jvm不保證finalize()一定被調用,也就是說,finalize()的調用是不確定的,這也就是為什么sun不提倡使用finalize()的原因.
測試代碼 package test;
- /**
- * 測試垃圾回收器與finalize()方法
- * @author Administrator
- */
- public class GcTest {
- public static void main(String[] args) {
- Book b1 = new Book();
- b1.setName("new");
- Book b2 = new Book();
- b2.setName("old");
- /*
- * 把b2引用指向null.讓b2引用所指的Book對象不在有引用指向它.
- * 垃圾回收器運行時,讓對象回收掉.
- */
- b2 = null;
- /*
- * 強行運行垃圾回收器.
- */
- System.gc();
- }
- }
- class Book{
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- protected void finalize() throws Throwable {
- // TODO Auto-generated method stub
- super.finalize();
- System.out.println(getName()+"--->執行GC工作.");
- }
- }
- package test;
- /**
- * 測試垃圾回收器與finalize()方法
- * @author Administrator
- */
- public class GcTest {
- public static void main(String[] args) {
- Book b1 = new Book();
- b1.setName("new");
- Book b2 = new Book();
- b2.setName("old");
- /*
- * 把b2引用指向null.讓b2引用所指的Book對象不在有引用指向它.
- * 垃圾回收器運行時,讓對象回收掉.
- */
- b2 = null;
- /*
- * 強行運行垃圾回收器.
- */
- System.gc();
- }
- }
- class Book{
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- protected void finalize() throws Throwable {
- // TODO Auto-generated method stub
- super.finalize();
- System.out.println(getName()+"--->執行GC工作.");
- }
- }
結果代碼
old--->執行GC工作.
【編輯推薦】