标记和清除采用相同的逻辑:从堆栈和静态存储区域开始,并跟踪全部句柄,寻找活动对象。然而,每次发现一个活动对象的时候,就会设置一个标记,为那个对象做上“记号”。但此时尚不收集那个对象。只有在标记过程结束,清除过程才正式开始。在清除过程当中,死锁的对象会被释放然而,不会进行任何形式的复制,因此倘若收集器决定压缩一个断续的内存堆,它经过移动周围的对象来实现。
“中止和复制”向咱们代表这种类型的垃圾收集并非在后台进行的;相反,一旦发生垃圾收集,程序就会中止运行。在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.