2007年12月19日

Java Garbage Collection

http://eason982.blogspot.com/2007/12/java-garbage-collection.html
自動記憶體管理也就是俗稱的垃圾收集(garbage-collection),可以讓程式員減輕許多負擔,也減少程式員犯錯的機會,所以相當受歡迎。從早期的 Smalltalk,Eiffel,到近期的 Java,C#,Python,REBOL,Ruby... 等,通通支援垃圾收集。垃圾收集差不多已經成了新一代高階程式語言必備的功能。

在 Java 中,你不需要主動刪除物件,而是由 Java 虛擬機器代勞。Java 虛擬機器會「持續追蹤」每個物件被使用的情形,如果某物件未被用到,Java 虛擬機器就會自動將其釋放。而要如何「持續追蹤」,實作細節留給 Java 虛擬機器的實作者發揮。

在早期,許多虛擬機器只是將垃圾收集實作成一個執行緒,一再進行檢查,遇到垃圾就釋放其記憶體。因為垃圾收集應該盡量不要影響到原程式的執行,所以虛擬機器將此執行緒的優先權設為 0(最低)。如此一來,當系統有其它執行緒在運作時,就不會進行垃圾收集,所以常常很久才會收集到垃圾,造成記憶體不足。但又不能因此調高其優先權,否則對 Java 的執行效率是一大打擊。所以,我們這些 Java 程式員的電腦 RAM 都要至少 256 MB,否則根本沒辦法順利執行 JBuilder 或 VisualAge for Java 等 Java 開發工具,因為這些開發工具本身就是專門吃記憶體的 Java 程式。我甚至在我的筆記型電腦上裝了 512MB 的 RAM。

於是許多人懷念起 C/C++ 來了,他們認為如果 Java 能同時支援自動記憶體管理和手動記憶體管理,那麼該有多好!他們甚至希望 Java 未來的版本能允許他們主動釋放記憶體,比方說:

MyBigObject obj = new MyBigObject();

// do something here...

delete obj;

如果你也這麼希望的話,我勸你早點死了這條心吧!Java 語言的主要精神之一是 robust,如果 Java 同時支援這兩種記憶體管理的話,可能會造成程式中有許多潛在的 Bug,記憶體不當存取的問題會比 C/C++ 更嚴重,所以是不可能這麼做的。

java.lang.System.gc() 或 java.lang.Runtime.gc() 的 gc 指的就是 garbage-collection,不過根據文件的說明,它的作用只是「建議」Java 虛擬機器快去收垃圾,而不「保證」會去收垃圾。文件都寫得如此謙虛了,你也不應該對它寄予太多厚望。對於記憶體資源消耗太多的缺失,目前你能做的是:

1. 改用一個記憶體管理方式好一點的虛擬機器:垃圾收集是一個豐富又龐大的主題。垃圾收集的
演算法有數百種可能,而且各有專長。許多虛擬機器採用的演算法都不太一樣,建議各位多去
比較幾家。

2. 少製造垃圾:許多時候你製造了一堆不該製造的垃圾,比方說:該用固定式陣列的時候卻用
Vector,該用 StringBuffer 的時候卻用 String...... 等等。這麼會製造垃圾,再多記憶體也不夠
用。

3. 不再使用的物件要盡早設定為 null,以便早點被當成垃圾清掉。

4. 花錢多買一些 RAM(砸錢解決問題)。

沒有留言: