標記和清除採用相同的邏輯:從堆棧和靜態存儲區域開始,並跟蹤全部句柄,尋找活動對象。然而,每次發現一個活動對象的時候,就會設置一個標記,爲那個對象做上「記號」。但此時尚不收集那個對象。只有在標記過程結束,清除過程才正式開始。在清除過程當中,死鎖的對象會被釋放然而,不會進行任何形式的複製,因此倘若收集器決定壓縮一個斷續的內存堆,它經過移動周圍的對象來實現。
「中止和複製」向咱們代表這種類型的垃圾收集並非在後臺進行的;相反,一旦發生垃圾收集,程序就會中止運行。在Sun公司的文檔庫中,可發現許多地方都將垃圾收集定義成一種低優先級的後臺進程,但它只是一種理論上的實驗,實際根本不能工做。在實際應用中,Sun的垃圾收集器會在內存減小時運行。除此之外,「標記和清除」也要求程序中止運行。"
參考自:《Thinking in Java》Ed3
下面用一個小實驗測試一下。
測試用例:
public
class Finalize {
static
int i = 0;
static
int d = 0;
public Finalize () {
i++;
System.out.println(
"No. " + i +
" is constructed.");
}
public
void finalize() {
d++;
System.out.println(
"No. " + d +
" is destroyed.");
}
}
含有main方法的公有類:
public
class FinalizeTest {
public
static
void main (String[] args) {
Finalize[] fArray =
new Finalize[10];
for (
int i = 0; i < 3; i ++) {
fArray[i] =
new Finalize();
System.out.println(fArray[i].hashCode());
}
/* Finalize f1 = new Finalize();
System.out.println(f1);
Finalize f2 = new Finalize();
System.out.println(f2);
Finalize f3 = new Finalize();
System.out.println(f3);
f1 = null;
System.out.println(f1);
f2 = null;
System.out.println(f2);
f3 = null;
System.out.println(f3);
System.gc();
*/
for (
int i = 0; i < 3; i++) {
fArray[i] =
null;
System.out.println(fArray[i]);
}
System.gc();
}
}
終端測試結果:
C:\Java\JVM\Finalize>javac *.java
C:\Java\JVM\Finalize>java FinalizeTest
No. 1 is constructed.
12677476
No. 2 is constructed.
33263331
No. 3 is constructed.
6413875
null
null
null
No. 1 is destroyed.
No. 2 is destroyed.
No. 3 is destroyed.