6.10.3 finalize方法

6.10.3 finalize方法

Java默认垃圾回收机制

在垃圾回收机制回收某个对象所占用的内存之前,通常要求程序调用适当的方法来清理资源,在没有明确指定清理资源的情况下,Java提供了默认机制来清理该对象的资源,这个机制就是finalize()方法。该方法是定义在Object类里的实例方法,方法原型为:
protected void finalize() throws Throwable
finalize方法返回后,对象消失,垃圾回收机制开始执行。方法原型中的throws Throwable表示它可以抛出任何类型的异常。
任何Java类都可以重写Object类的finalize()方法,在该方法中清理该对象占用的资源。

finalize方法不一定会被调用

如果程序终止之前始终没有进行垃圾回收,则不会调用失去引用对象的finalize方法来清理资源。
只有当程序认为需要更多的额外内存时,垃圾回收机制才会进行垃圾回收。因此,完全有可能出现这样一种情形:

  • 某个失去引用的对象只占用了少量内存,而且系统没有产生严重的内存需求,因此垃圾回收机制并没有试图回收该对象所占用的资源,所以该对象的finalize()方法也不会得到调用

finalize方法特点

finalize()方法具有如下4个特点:

  1. 永远不要主动调用某个对象的finalize()方法,该方法应交给垃圾回收机制调用。
  2. finalize()方法何时被调用,是否被调用具有不确定性,不要把finalize()方法当成一定会被执行的方法.
  3. JVM执行可恢复对象的finalize()方法时,可能使该对象或系统中其他对象重新变成可达状态。
  4. JVM执行finalize()方法时出现异常时,垃圾回收机制不会报告异常,程序继续执行。

由于finalize方法并不一定会被执行,因此如果想清理某个类里打开的资源,则不要放在finalize方法中进行清理

如何强制调用可恢复对象的finalize()方法

finalize()方法要等到系统垃圾回收的时候才会执行,但是可能系统都不会进行垃圾回收。如果有必要,可以通过如下两个方法来强制执行所有可恢复对象的finalize()方法:

  • Runtime.getRuntime().runFinalization();
  • System.runFinalization();

实例 可恢复状态状态对象重新变成可达状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class FinalizeTest {
private static FinalizeTest ft = null;

public void info() {
System.out.println("测试资源清理的finalize方法");
}

public static void main(String[] args) throws Exception {
// 创建FinalizeTest对象立即进入可恢复状态
new FinalizeTest();
// 通知系统进行资源回收
System.gc(); // ①
// 强制垃圾回收机制调用可恢复对象的finalize()方法
// Runtime.getRuntime().runFinalization(); // ②
System.runFinalization(); // ③
// 执行对象的方法,如果注释掉上面的`System.gc();`,则不会强制垃圾回收,finalize方法不会执行,ft为null,则下面语句将会抛出空指针异常.
// 如果注释掉上面的`System.runFinalization();`,则finalize方法要等到系统进行垃圾回收时才会执行,系统可以不会进行垃圾回收,下面语句还是会抛出空指针异常.
// `System.runFinalization();`将会强制执行所有可恢复对象的finalize方法.
// 下面语句将会抛出空指针异常
ft.info();
}

public void finalize() {
// 重新引用 可恢复状态的对象,该对象将重新变成可达状态
ft = this;
}
}