我在thinking in Java中看見以下一段代碼。
//:Garbage.java
//Demonstration of the garbage
//collector and finalization
class Chair {
static boolean gcrun=false;
static boolean f=false;
static int created=0;
static int finalized=0;
int i;
Chair(){
i=++created;
if(created==47)
System.out.println("Created 47");
}
protected void finalize(){
if(!gcrun){
gcrun=true;
System.out.println(
"Beginning to finalize after"+created+
"Chairs have been created");
}
if(i==47){
System.out.println(
"Finalizing Chair #47,"+
"Setting flag to stop Chair creation");
f=true;
}
finalized++;
if(finalized>=created)
System.out.println(
"All"+finalized+"finalized");
}
}
public class Garbage{
public static void main(String[] args){
if(args.length==0){
System.out.println("Usage:
"+
"java Garbage before
or:
"+
"java Garbage after");
return;
}
while(!Chair.f){
new Chair();
new String("To take up space");
}
System.out.println(
"After all chairs have been created:
"+
"total created ="+Chair.created+
",total finalized ="+Chair.finalized);
if(args[0].equals("before")){
System.out.println("gc():");
System.gc();
System.out.println("runFinalization():");
System.runFinalization();
}
System.out.println("bye");
if(args[0].equals("after"))
System.runFinalizersOnExit(true);
}
}///:-
為什麼執行java Gerbage before
以後,當所有對象創建完(比如8000個),這時只清除了2000個(不定)
應該只能創建47個對象啊
分析: 首先,在一個循環當中創建對象,並且只是創建,而不引用,也就是說這個對象會自動的被系統當作垃圾處理掉。但請注重,finalize()方法並不是馬上就會執行的,執行的時間完全由系統來決定。所以很有可能的情況是已經創建了20000個對象,才開始其中的某一個對象的清除工作(這可能和時間或者系統內容的占用有關)。看finalize()方法中的一段代碼:
if (!gcrun) {
gcrun = true;
System.out.println(
"
Beginning to finalize after" + created + "Chairs have been created
at ");
}
就會出現這樣的結果:
Beginning to finalize after 25038 Chairs have been created
這時對象的創建過程仍在繼續(因為已經Finalize的對象還不滿47個,Chair.f還是false)。所以Chair.created會繼續增加。
直到有47個對象被清除了,Chair.f被置成true了,創建對象的循環才結束。看main方法中的一段代碼:
System.out.println(
"
After all chairs have been created:
"
+ "total created ="
+ Chair.created
+ ",total finalized ="
+ Chair.finalized+"
");
如上所說,Chair.created是不斷增加的,而在這段代碼執行之前,又會有N個對象被釋放掉了,所以finalized也增加了。
結果可能是這樣的:
total created =29096,total finalized =73
其實這一過程和你使用的JVM有很大關系,執行結果可能會很不相同。但有一點是可以肯定的,那就是我們無法確定JVM什麼時候做對象的清除工作(這也是Thinking in java中這段代碼的想要說明的),可能會在這個對象剛剛“無用”的時候就清除掉了,也可能滯後幾秒,甚至永遠不清除。
假如你的開發環境支持跟蹤的話,你可以以STEP的方式運行,你會看到運行結果大不相同。給你看看我的運行結果:
Created 47
Beginning to finalize after25038Chairs have been created
Finalizing Chair #47,Setting flag to stop Chair creation
After all chairs have been created:
total created =45993,total finalized =1800
gc():
runFinalization():
bye
All45993finalized
注重最後一行,因為人為的停頓,JVM有足夠的時間將所有的對象都清除了。
結論:
不能指望finalize()方法能穩定的工作,尤其不能依靠它來做文件的關閉等操作,由於finalize()的不確定性,往往得不到你想要的結果。事實上我們只需要知道所有無用的對象,JVM會自己清除就夠了。