Effective Java代码规则之八:避免使用终结器和清除器

1、解释

终结器(finalizer)是不可预测的,通常是危险的,并且通常是不必要的。 它们的使用会导致不稳定的行为,性能不佳和可移植性问题。 终结器有一些有效用途,我们将在本项后面介绍,但作为一项规则,您应该避免使用它们。 从Java 9开始,终结器已被弃用,但它们仍被Java库使用。 Java 9用清洁器(cleaner)替代终结器。

清洁器比终结器危险性小,但仍然不可预测,缓慢且通常不必要。

终结器和清除器的问题如下:

  • Java 语言规范不仅不保证终结器或者清除器会被及时地执行,而且根本就不保证它们会被执行;
  • 在执行终结器机制过程中,未捕获的异常会被忽略,并且该对象的终结器机制也会终止;
  • 使用终结器和清洁器机制会导致严重的性能问题。
  • 终结方法有一个严重的安全问题,它们为终结方法攻击( finalizer attack ) 打开了类的大门。

2、优点

可以避免使用终结器和清除器带来的问题。

3、缺点

可能会丧失使用终结器和清除器的一些好处:

  • 用终结器充当“安全网”

这样做井不能保证终结器或者清除器会被及时地运行,但是迟一点释放资源总比永远不释放要好(当close方法被忘记调用的时候)。

  • 终止非关键的本地资源

在JNI中,我们可以用清除器来释放非关键的本地资源。如果要释放关键本地资源,仍然要调用close方法。

4、最佳实践

在实际工作中,如果类的对象中封装的资源(例如文件或者线程)确实需要终止,应该怎么做才能不用编写终结器或者清除器呢?只需让类实现AutoCloseable接口,在使用try-catch-resources语法创建的资源抛出异常后,JVM会自动调用close方法进行资源释放,当正常退出时try-block时候也会调用close方法。

public class AutoCloseAbleClass implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("i am close");
}
public void dosomething() {
System.out.println("do something");
}
}

//使用try-catch-resources语法
try (AutoCloseAbleClass autoCloseable = new AutoCloseAbleClass()) {
autoCloseable.dosomething();
} catch (Exception e) {
e.printStackTrace();
}

Effective Java代码规则之八:避免使用终结器和清除器

专业从事软件研发工作多年,在软件设计、开发、测试、研发管理等领域里经验丰富,感兴趣的朋友可以关注我的头条号,相信一定会有所收获。

如果有软件研发方面的问题,可以咨询我。

谢谢!


分享到:


相關文章: