finalizejava
㈠ 為什麼在java中不使用finalize方法
Java提供finalize()方法,垃圾回收器准備釋放內存的時候,會先調用finalize()。
(1).對象不一定會被回收。
(2).垃圾回收不是析構函數。
(3).垃圾回收只與內存有關。
(4).垃圾回收和finalize()都是靠不住的,只要JVM還沒有快到耗盡內存的地步,它是不會浪費時間進行垃圾回收的。
有時當撤消一個對象時,需要完成一些操作。例如,如果一個對象正在處理的是非Java 資源,如文件句柄或window 字元字體,這時你要確認在一個對象被撤消以前要保證這些資源被釋放。為處理這樣的狀況,Java 提供了被稱為收尾(finalization )的機制。使用該機制你可以定義一些特殊的操作,這些操作在一個對象將要被垃圾回收程序釋放時執行。
要給一個類增加收尾(finalizer ),你只要定義finalize ( ) 方法即可。Java 回收該類的一個對象時,就會調用這個方法。在finalize ( )方法中,你要指定在一個對象被撤消前必須執行的操作。垃圾回收周期性地運行,檢查對象不再被運行狀態引用或間接地通過其他對象引用。就在對象被釋放之前,Java 運行系統調用該對象的finalize( ) 方法。
finalize()方法的通用格式如下:
protected void finalize( )
{
// finalization code here
}
其中,關鍵字protected是防止在該類之外定義的代碼訪問finalize()標識符。該標識符和其他標識符將在第7章中解釋。
理解finalize( ) 正好在垃圾回收以前被調用非常重要。例如當一個對象超出了它的作用域時,finalize( ) 並不被調用。這意味著你不可能知道何時——甚至是否——finalize( ) 被調用。因此,你的程序應該提供其他的方法來釋放由對象使用的系統資源,而不能依靠finalize( ) 來完成程序的正常操作。
注意:如果你熟悉C ,那你知道C 允許你為一個類定義一個撤消函數(destructor ),它在對象正好出作用域之前被調用。Java不支持這個想法也不提供撤消函數。finalize() 方法只和撤消函數的功能接近。當你對Java 有豐富經驗時,你將看到因為Java使用垃圾回收子系統,幾乎沒有必要使用撤消函數。
理解finalize()-析構函數的替代者
by Tim Gooch
在許多方面,Java 類似於 C++。Java 的語法非常類似於 C++,Java 有類、方法和數據成員;Java 的類有構造函數; Java 有異常處理。
但是,如果你使用過 C++ 會發現 Java 也丟掉一些可能是你熟悉的特性。這些特性之一就是析構函數。取代使用析構函數,Java 支持finalize() 方法。
在本文中,我們將描述 finalize() 與 C++ 析構函數的區別。另外,我們將創建一個簡單的 Applet 來演示 finalize() 是如何工作的。
最終的界限
與 Java 不同,C++ 支持局部對象(基於棧)和全局對象(基於堆)。因為這一雙重支持,C++ 也提供了自動構造和析構,這導致了對構造函數和析構函數的調用,(對於堆對象)就是內存的分配和釋放。
在 Java 中,所有對象都駐留在堆內存,因此局部對象就不存在。結果,Java 的設計者覺得不需要析構函數(象 C++ 中所實現的)。
取而代之,Java 定義了一個特殊的方法叫做finalize() ,它提供了 C++ 析構函數的一些功能。但是,finalize() 並不完全與 C++ 的析構函數一樣,並可以假設它會導致一系列的問題。finalize() 方法作用的一個關鍵元素是 Java 的垃圾回收器。
垃圾回收器
在 C/C++、Pascal和其他幾種多種用途的編程語言中,開發者有責任在內存管理上發揮積極的作用。例如,如果你為一個對象或數據結構分配了內存,那麼當你不再使用它時必須釋放掉該內存。
在 Java 中,當你創建一個對象時,Java 虛擬機(JVM)為該對象分配內存、調用構造函數並開始跟蹤你使用的對象。當你停止使用一個對象(就是說,當沒有對該對象有效的引用時),JVM 通過垃圾回收器將該對象標記為釋放狀態。
當垃圾回收器將要釋放一個對象的內存時,它調用該對象的finalize() 方法(如果該對象定義了此方法)。垃圾回收器以獨立的低優先順序的方式運行,只有當其他線程掛起等待該內存釋放的情況出現時,它才開始運行釋放對象的內存。(事實上,你可以調用System.gc() 方法強制垃圾回收器來釋放這些對象的內存。)
在以上的描述中,有一些重要的事情需要注意。首先,只有當垃圾回收器釋放該對象的內存時,才會執行finalize()。如果在 Applet 或應用程序退出之前垃圾回收器沒有釋放內存,垃圾回收器將不會調用finalize()。
其次,除非垃圾回收器認為你的 Applet 或應用程序需要額外的內存,否則它不會試圖釋放不再使用的對象的內存。換句話說,這是完全可能的:一個 Applet 給少量的對象分配內存,沒有造成嚴重的內存需求,於是垃圾回收器沒有釋放這些對象的內存就退出了。
顯然,如果你為某個對象定義了finalize() 方法,JVM 可能不會調用它,因為垃圾回收器不曾釋放過那些對象的內存。調用System.gc() 也不會起作用,因為它僅僅是給 JVM 一個建議而不是命令。
結論
然而有益的是,Java 的自動垃圾回收器不會失去平衡。作為便利的代價,你不得不放棄對系統資源釋放的控制。不象 C++ 中的析構函數,Java Applet 不會自動執行你的類中的finalize() 方法。事實上,如果你正在使用 Java 1.0,即使你試圖強制它調用finalize() 方法,也不能確保將調用它。
因此,你不應當依靠finalize() 來執行你的 Applet 和應用程序的資源清除工作。取而代之,你應當明確的清除那些資源或創建一個try...finally 塊(或類似的機制)來實現。
finalize方法是與Java編程中的垃圾回收器有關系。即:當一個對象變成一個垃圾對象的時候,如果此對象的內存被回收,那麼就可以調用系統中定義的finalize方法來完成
當然,Java的內存回收可以由JVM來自動完成。如果你手動使用,則可以使用上面的方法。
舉例說明:
㈡ JAVA里finalize()方法是干什麼用的
類的finalize()方法,可以告訴垃圾回收器應該執行的操作,該方法從Object類繼承而來。
在從堆中永久刪除對象之前,垃圾回收器調用該對象的finalize()方法。注意,無法確切地保證垃圾回收器何時調用該方法,也無法保證調用不同對象的方法的順序。即使一個對象包含另一個對象的引用,或者在釋放一個對象很久以前就釋放了另一個對象,也可能會以任意的順序調用這兩個對象的Finalize方法。如果必須保證採用特定的順序,則必須提供自己的特有清理方法。
㈢ java中finalize()方法在哪個類中
它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個對象調用的。
㈣ java中finalize()方法的使用
設計一個對象重生的代碼來演示,如下:
具體解析如下:
為方便起見, 把a,b兩個變數所指的內存空間就叫做a和b。
A a = new A(new B("allen" , 20)) ; //此時a和b都是reachable, unfinalized狀態。
a = null ;
這之後, a和b的狀態會在某一個時刻變成unreachable, unfinalized或者a和b直接變成f-reachable, unfianlized。
然後在某個時刻,GC檢測到a和b處於unfinalized狀態,就將他們添加到F-queue,並將狀態改為f-reachable finalizable。
之後分兩種情況:
1、 GC從F-queue中首先取出a, 並被某個線程執行了finalize(), 也就相當於被某個活動的線程持有, a狀態變成了reachable, finalized.。
此時由於a被c對象所引用,所以之後不會變成unreachable finalized而被銷毀(重生) 與此同時,b由於一直被a所引用,,所以b的狀態變成了reachable, finalizable.。
然後在某個時刻被從F-queue取出, 變成reachable, finalized狀態。
2、GC從F-queue中首先取出b,並被某個線程執行了finalize(), 狀態變成reachable finalized. 然後a也類似, 變成reachable finalized狀態, 並被c引用,重生。
(4)finalizejava擴展閱讀:
盡量避免使用finalize():
1、finalize()不一定會被調用, 因為java的垃圾回收器的特性就決定了它不一定會被調用。
2、就算finalize()函數被調用, 它被調用的時間充滿了不確定性, 因為程序中其他線程的優先順序遠遠高於執行finalize()函數線程的優先順序。也許等到finalize()被調用, 資料庫的連接池或者文件句柄早就耗盡了。
3、如果一種未被捕獲的異常在使用finalize方法時被拋出,這個異常不會被捕獲,finalize方法的終結過程也會終止,造成對象出於破壞的狀態。被破壞的對象又很可能導致部分資源無法被回收, 造成浪費。
4、finalize()函數和垃圾回收器的運行本身就要耗費資源, 也許會導致程序的暫時停止。
㈤ Java中final,finally和finalize的區別是什麼
一、final :
1、修飾符(關鍵字) 如果一個類被聲明為final,意味著它不能再派生新的子類,不能作為父類被繼承。因此一個類不能及被聲明為abstract,又被聲明為final的。
2、將變數或方法聲明為final,可以保證他們使用中不被改變。被聲明為final的變數必須在聲明時給定初值,而以後的引用中只能讀取,不可修改,被聲明為final的方法也同樣只能使用,不能重載。
二、finally:
在異常處理時提供finally塊來執行清楚操作。如果拋出一個異常,那麼相匹配的catch語句就會執行,然後控制就會進入finally塊,如果有的話。
三、finalize:
是方法名。java技術允許使用finalize()方法在垃圾收集器將對象從內存中清除之前做必要的清理工作。這個方法是在垃圾收集器在確定了,被清理對象沒有被引用的情況下調用的。
finalize是在Object類中定義的,因此,所有的類都繼承了它。子類可以覆蓋finalize()方法,來整理系統資源或者執行其他清理工作。