垃圾收集器(記憶體回收器)的行為線
Java 程式設計師不需要監視記憶體分配,因為垃圾收集器會自動管理記憶體。垃圾收集器由 Java 虛擬機器 (JVM) 運行。垃圾收集器是一個低優先權進程,它定期運行並釋放不再需要的物件使用的記憶體。不同的 JVM 有不同的垃圾收集演算法。使用了多種演算法,例如:引用計數演算法或標記和抓取演算法。
在 Java 中運行垃圾收集器
當可用記憶體較低時,JVM 通常會執行垃圾收集器。但垃圾收集器的運作並不能保證總是有足夠的空閒記憶體。如果恢復後仍然沒有足夠的內存,JVM 會拋出 OutOfMemoryError 異常。請注意,JVM 在拋出異常之前必須至少執行一次垃圾收集器。您可以請求垃圾收集器在 Java 中運行,但不能強制執行此操作。
請求運行垃圾收集器
若要發出請求,您可以呼叫下列方法之一:
System.gc()
Runtime.getRuntime().gc()
適合運行垃圾收集器
當物件不再可供活動串流使用時,必須將其丟棄。一個物體可能會在不同的情況下被處置:
- 如果引用某個物件的參考類型變數被設定為“0”,且沒有其他引用對該物件進行處理,則必須釋放該物件。
- 如果建立引用一個對象的參考類型變數來引用另一個對象,並且沒有其他引用對該對象進行處理,則必須釋放該對象。
- 當方法退出時,在方法中本地建立的物件將被丟棄,除非它們是從該方法導出的(即作為異常返回或拋出)。
- 如果沒有一個物件可供活動線程使用,則相互引用的物件可能會被處置。
讓我們來看一個例子:
public class TestGC
{
public static void main(String [] args)
{
Object o1 = new Integer(3);
Object o2 = new String("Tutorial");
o1 = o2;
o2 = null;
}
}
在此範例中
Integer
,最初由 o1 引用的物件(整數)可以在第 3 行之後處理,因為 o1 現在引用該物件
String
(字串)。即使創建 o2 來引用 null,該物件
String
(字串)也是不可回收的,因為 o1 引用了它。
最終確定
finalize()
Java 技術可讓您在垃圾收集器從記憶體中檢索物件之前使用方法(finalize) 進行必要的清理。當垃圾收集器確定不再有對該物件的參考時,垃圾收集器會對該物件呼叫此方法。這是在 class 中描述的
Object
,這意味著它被所有類別繼承。子類別重寫該方法
finalize()
以將其自身從系統資源中釋放出來或進行另一次清理:
protected void finalize() throws Throwable
如果方法拋出未註冊的異常
finalize()
,則該異常將被忽略並且該物件的終結將停止。此方法
finalize()
在物件的生命週期內只會被呼叫一次。可以對
finalize()
任何物體使用某種方法來保護其免遭處置。但在這種情況下,垃圾收集器不再
finalize()
為此物件啟動。
finalize()
在物件被垃圾收集之前,該方法始終會被呼叫一次。然而,對於給定對象,該方法
finalize()
可能不會在其存在的整個持續時間內被激活,因為它可能不會受到處置。
概括
在本節中,我們研究了垃圾收集過程,這是 Java 語言中的記憶體管理技術。不能強制垃圾收集。我們了解了使物件符合回收條件的不同方法,並了解了
finalize()
在垃圾收集器回收物件之前呼叫該方法。
鍛鍊
問: 第 7 行之後有多少物品會被處置?
public class TutorialGC
{
public static void main(String [] args)
{
Object a = new Integer(100);
Object b = new Long(100);
Object c = new String("100");
a = null;
a = c;
c = b;
b = a;
}
}
答案選項: A. 0 B. 1 C. 2 D. 3 E. 程式碼無法編譯
正確選項: B
說明:在第 1、2、3 行建立的三個物件中,只有該物件
Integer
必須在第7 行結尾.最初引用對象的變數引用 a在第 5 行
Integer
引用了該對象。因此,必須在第 5 行之後處理該對象,因為沒有引用它的變數。變數和引用第6行和第7行中的對象和對象,因此它們是不可回收的。
String
Integer
b
c
String
Long
GO TO FULL VERSION