Java教室: Garbage Collection 清除物件的順序 (轉)
----------------------------------------------------------------
(作者 : 艾群科技 蕭松瀛)
與 C 的其中一個差別就在於寫 C 程式時,如果我們 new 了一個
物件,同時我們也必須下 delete 來清除它, C 語言的核心並不會判斷
這個物件是否不再使用,而在程式時,需不需要將物件移除,也全都
由使用者自行控制。其實這個原意很好,但是寫到大型專案,或是 Multi
-Thread 程式時,往往這些物件會變成難以控制,有時候我們甚至會試圖
去使用一個已經不存在的指標。
在 Java 中, JVM 幫我們管理這一層,因此當物件不在被使用時, JV
M 會在"適當"的時間點將它由記憶體中移除。
所有的物件均繼承 ,因此 Object 這個物件中,有一個很有用
的 method 叫做 finalize() ,這一個 method 依照定義,當 Garbage C
ollection 要將這個物件移除前會先呼叫這個物件的 finalize() 。也就
是說,當我們在實作我們的 Class 的時候,最好將這一個 method overr
。這樣一來,當 Garbage Collection 要清除物件的時候,就會執行
到我們自己寫的 finalize()。
因此我們設計了底下這個物件,這個物件在我們建立時,需要帶入一個
int 值,這一個 int 值,而當 finalize() 被執行的時候,他會將這個
int 值列印出來,好讓我們知道 Garbage Collection正準備清除哪一個
物件。
public class testobject
{
private int itell;
public testobject()
{
this.itell = 0;
}
public testobject(int i)
{
this.itell = i;
}
public void finalize()
{
System.out.println("testobject id = "+itell);
}
}
接著,我寫了底下這一個 testfinalize.java ,這一個 testfinalize
.java 會宣告一個陣列,這一個陣列中,會存放 testobject 物件,屆時
我會將這一個陣列設為 null ,表示我不再使用這一個陣列了。
public class testfinalize
{
public static void main(String argv[])
{
testobject [] testo = new testobject[2];
testo[0] = new testobject(1);
testo[1] = new testobject(2);
testo = null;
System.out.println("finish...");
}
}
執行的結果是
C:tempjavajava testfinalize
finish...
C:tempjava
奇怪,是 garbage collection 沒有執行 finalize() 嗎?? 不是的,
是 garbage collection 根本沒有被啟動,在前面說過,garbage collec
tion 會在適當的時機啟動,而這一個 testfinalize 程式很小, JVM 認
為不需要執行 Garbage Collection ,因此程式結束,記憶體釋放。
是不是這樣就沒辦法知道 garbage collection 做了時麼事情??不是我
們還可以透過兩個 method 來建議 JVM 執行 garbage collection,一個
是 System.gc(); ,另外一個建議的方式是 Runtime.getRuntime().gc()
, System.gc() 也會執行 Runtime.getRuntime().gc() ,不論哪一個,
他們都會建議 JVM 去執行另外一個 Thread ,這一個 Thread 會掃瞄所
有沒有被用到的物件,將他們清除,並且取得他們所佔用的記憶體。因此
我們將 testfinalize.java 加上一行如下
public class testfinalize
{
public static void main(String argv[])
{
testobject [] testo = new testobject[2];
testo[0] = new testobject(1);
testo[1] = new testobject(2);
testo = null;
System.gc();
System.out.println("finish...");
}
}
Compile 之後執行結果如下
C:tempjavajava testfinalize
testobject id = 1
testobject id = 2
finish...
C:tempjava
沒錯,我們看到了 testobject id = 1 以及 testobject id = 2 這兩
行了。
問題就這樣解決了嗎??非也!他事先清除陣列 testo[0] 接著再清除 t
esto[1] 還是有其他的順序??
首先,我們先來看看 JLS 中對於 Garbage Collection 順序的說明
12.6.2 Finalizer Invocations are Not Ordered
The Java programming language imposes no ordering on finalize
method calls. Finalizers may be called in any order, or even con
currently. As an example, if a circularly linked group of unfina
lized objects becomes unreachable (or finalizer-reachable), then
all the objects may become finalizable together. Eventually, th
e finalizers for these objects may be invoked, in any order, or
even concurrently using multiple threads. If the automatic stora
ge manager later finds that the objects are unreachable, then th
eir storage can be reclaimed.
It is straightforward to implement a class that will cause a s
et of finalizer-like methods to be invoked in a specified order
for a set of objects when all the objects become unreachable. De
fining such a class is left as an exercise for the reader.
依照這個規格說明,我們發現, JVM 並沒有依照一定的順序來清除物
件,然而實際上呢 ??
我們再修改 testfinalize.java 讓他成為底下的
public class testfinalize
{
public static void main(String argv[])
{
testobject [] testo = new testobject[2];
testo[1] = new testobject(2);
testo[0] = new testobject(1);
testo = null;
System.gc();
System.out.println("finish...");
}
}
也就是這一次,我們先產生 new testobject(2) 並且將他放到 testo[
1] 然後再產生 new testobject(1),接著放到 testo[0] 。
執行結果如下
C:tempjavajava testfinalize
testobject id = 2
testobject id = 1
finish...
C:tempjava
沒錯,我們實際上執行這個程式的結果是先產生的物件, Garbage Col
lection 先將他移除。
至於時麼時候該使用 finalize() ? 通常僅需要記住一個原則,就是如
果在產生物件的同時,我們有使用到一些資源,譬如 JC 連線,譬如開
了個 socket 到另外一臺機器,甚至開了個 Server等等,那麼在
finalize() 的時候,我們最好就需要嘗試著將這些資源給釋放。
執行環境
1. Sun Ultra 10
1.3.0 Hotspot Client
2. 2000
JDK 1.3.0_01 Hotspot Client
----------------------------------------------------------------
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988243/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入理解Java中的Garbage CollectionJava
- Java的垃圾回收(Garbage Collection)機制Java
- [Javascript] garbage collectionJavaScript
- 垃圾收集機制(Garbage Collection)批判 (轉)
- JAVA物件的初始化順序Java物件
- C語言垃圾回收(Garbage Collection)C語言
- JVM垃圾回收機制(Garbage Collection)JVM
- [Memory leak] 3. Garbage collection in Closure
- JAVA中取順序號 (轉)Java
- python ref counting based garbage collectionPython
- js物件遍歷順序JS物件
- 程式碼說事 之 建立java物件的初始化順序Java物件
- Java常見知識點彙總(⑰)——垃圾回收機制(garbage collection-GC)JavaGC
- 【原創】【Android】揭祕 ART 細節 ---- Garbage collectionAndroid
- JavaScript遍歷物件屬性順序JavaScript物件
- c#物件初始化順序C#物件
- Oracle對於物件名的解釋順序Oracle物件
- java類初始化的順序Java
- Java類的基本執行順序Java
- Java實現順序表Java
- Java初始化順序Java
- java類載入順序Java
- Garbage Collection 一直在執行? 還是需要時才啟動? (轉)
- Java的類的例項化順序Java
- 從ASP.NET Core 3.0 preview 特性,瞭解CLR的Garbage CollectionASP.NETView
- 請教一個從Collection到Map保持排序順序不變的問題排序
- 按照陣列順序給物件重新組合成新物件陣列物件
- Java中class的初始化順序Java
- 關於java的初始化順序Java
- 學Java,Java書籍的最佳閱讀順序Java
- Java父子類載入順序Java
- java運算子優先順序Java
- Java 類初始化順序Java
- Java類初始化順序Java
- ☕[JVM技術指南](1)垃圾回收子系統(Garbage Collection System)之回收標記和物件引用的介紹JVM物件
- 淺談PHP5中垃圾回收演算法(Garbage Collection)的演化PHP演算法
- Python的方法解析順序(MRO)[轉]Python
- javascript 字串字元順序反轉JavaScript字串字元