详解Java的finalize()方法:在垃圾回收器将对象从内存中清除出去之前,调用对象的该方法

  • Post category:Java

Java中的finalize()方法是Object类中的一个方法,该方法用于在对象被垃圾回收之前执行清理操作。finalize()方法的作用是在垃圾回收器将对象从内存中清除之前执行一些操作,例如释放连接、关闭文件等。

finalize()方法的声明如下:

protected void finalize() throws Throwable { }

该方法的访问控制修饰符为protected,返回值为void,抛出异常类型为Throwable。

finalize()方法的执行顺序:

  • Java虚拟机(JVM)中的垃圾回收器监控堆内存中的对象,发现无人引用的对象会被标记为垃圾对象。
  • 通过finalize()方法判断当前对象是否可达。
  • 如果对象可达,则不执行finalize()方法,如果不可达,则执行finalize()方法。最后执行垃圾对象的回收操作。

在Java中,finalize()方法有一些需要注意的地方,例如:

  1. finalize()方法并不保证一定会执行。

  2. Java中存在finalize()方法与垃圾回收的线程优先级问题。垃圾回收的线程优先级低于主线程,因此,finalize()方法的执行会受到影响。如果处理的是非常重要的资源,如数据库连接等,建议使用try-finally结构在程序完成时手动清理资源。

下面给出一个示例说明:

public class MyObject {
    private String name;

    public MyObject(String name) {
        this.name = name;
    }

    protected void finalize() throws Throwable {
        System.out.println(this.name + "被回收了");
    }

    public static void main(String[] args) throws Exception {
        MyObject obj1 = new MyObject("对象1");
        MyObject obj2 = new MyObject("对象2");

        obj1 = null;//将obj1设置为null,使其成为一个垃圾对象
        System.gc();//强制JVM进行垃圾回收
        Thread.sleep(500);//等待一段时间,让JVM有时间处理垃圾对象
        obj2 = null;//将obj2设置为null,使其成为一个垃圾对象
        System.gc();//强制JVM进行垃圾回收
        Thread.sleep(500);//等待一段时间,让JVM有时间处理垃圾对象
    }
}

运行该程序,可以看到如下输出结果:

对象1被回收了

从输出结果可以看出,finalize()方法只执行了一次,而且只清理了一个对象。这是由于Java中的finalize()方法不保证一定会执行,可以通过System.gc()方法来触发gc,但是gc不一定会立即执行,需要等待一段时间才能看到回收的结果。

下面再给出一个示例说明:

public class MyResource {
    private String name;

    public MyResource(String name) {
        this.name = name;
    }

    public void dispose() {
        System.out.println(this.name + "被释放了");
    }

    protected void finalize() throws Throwable {
        dispose();//手动清理资源
    }

    public static void main(String[] args) {
        MyResource obj1 = new MyResource("资源1");
        MyResource obj2 = new MyResource("资源2");

        obj1.dispose();//手动释放资源

        obj1 = null;//将obj1设置为null,使其成为一个垃圾对象
        obj2 = null;//将obj2设置为null,使其成为一个垃圾对象
        System.gc();//强制JVM进行垃圾回收
    }
}

运行该程序,可以看到如下输出结果:

资源1被释放了

从输出结果可以看出,这次程序在手动释放资源时,确保了资源被回收的过程,手动释放资源是更加可靠的方法,但也需要考虑到编程中的复杂性和困难度。