finalize()是由JVM自動調用的,你能夠用System.gc(),但JVM不必定會馬上執行,JVM感受內存空間有限時,纔會開始執行finalize(),至於新的對象建立個數和被收集個數不一樣是由於收集的對象只和JVM的垃圾收集策略有關。java
finalize()和gc()
(1)問題:finalize()函數是幹嗎的?Java不是有Garbage Collection(如下簡稱gc)來負責回收內存嗎?
回答:
gc 只能清除在堆上分配的內存(純java語言的全部對象都在堆上使用new分配內存),而不能清除棧上分配的內存(當使用JNI技術時,可能會在棧上分配內 存,例如java調用c程序,而該c程序使用malloc分配內存時).所以,若是某些對象被分配了棧上的內存區域,那gc就管不着了,對這樣的對象進行 內存回收就要靠finalize().
舉個例子來講,當java 調用非java方法時(多是c),在非java代碼內部也許調用了malloc()函數來分配內存,並且除非調用那個了 free() 不然不會釋放內存(由於free()是c的函數),這個時候要進行釋放內存的工做,gc是不起做用的,於是須要在finalize()內部的一個固有方法 調用它(free()).
finalize的工做原理應該是這樣的:一旦垃圾收集器準備好釋放對象佔用的存儲空間,它首先調用finalize(),並且只有在下一次垃圾收集過程當中,纔會真正回收對象的內存.因此若是使用finalize(),就能夠在垃圾收集期間進行一些重要的清除或清掃工做.程序員
一般,你不能期望finalize( ),你必須建立其它的「清除」方法,而且明確地調用它們。看來,finalize( )只能存在於程序員很難用到的一些晦澀用法裏了。不過,finalize( )還有一個有趣的用法,它並不依賴於每次都要對finalize( )進行調用,這就是對象「終結條件」的驗證。
當你對某個對象再也不感興趣,也就是它能夠被清除時,這個對象應該處於某種狀態,使它佔用的內存能夠被安全地釋放。例如,要是對象表明了一個打開的文 件,在對象被回收前程序員應該關閉這個文件。只要對象中存在沒有被適當清除的部分,你的程序就存在很隱晦的錯誤。finalize( )的價值在於能夠用來最終發現這種狀況,儘管它並不老是會被調用。若是某次
finalize( )的動做使得bug被發現,那你就可據此找出問題所在——這纔是最重要的安全
1 class Book { 2 boolean checkedOut = false; 3 Book(boolean checkOut) { 4 checkedOut = checkOut; 5 } 6 void checkIn() { 7 checkedOut = false; 8 } 9 public void finalize() { 10 if(checkedOut) 11 System.out.println("Error: checked out"); 12 // Normally, you'll also do this: 13 // super.finalized(); 14 } 15 } 16 public class TerminationCondition { 17 public static void main(String[] args) { 18 Book novel = new Book(true); 19 // Proper cleanup: 20 novel.checkIn(); 21 // Drop the reference, forget to clean up: 22 new Book(true); 23 // Force garbage collection & finalization: 24 System.gc(); 25 } 26 }