Java9垃圾回收方法finalize() 原理解析

2020-02-25 14:02:32刘景俊

1: finalize() 方法

finallize() 方法是Object类的方法, 用于在类被GC回收时 做一些处理操作, 但是JVM并不能保证finalize(0 ) 方法一定被执行,
由于finalize()方法的调用时机具有不确定性,从一个对象变得不可到达开始,到finalize()方法被执行,所花费的时间这段时间是任意长的。我们并不能依赖finalize()方法能及时的回收占用的资源,可能出现的情况是在我们耗尽资源之前,gc却仍未触发,因而通常的做法是提供显示的close()方法供客户端手动调用
所以一般不建议使用finalize 方法, JDK9 开始已久被废除

总结缺点

1: finalize机制本身就是存在问题的。

2:finalize机制可能会导致性能问题,死锁和线程挂起。

3:finalize中的错误可能导致内存泄漏;如果不在需要时,也没有办法取消垃圾回收;并且没有指定不同执行finalize对象的执行顺序。此外,没有办法保证finlize的执行时间。
遇到这些情况,对象调用finalize方法只有被无限期延后

- 观察finalize方法延长类生命周期#

class User{
   
  public static User user = null;
 
  @Override
  protected void finalize() throws Throwable {
    System.out.println("User-->finalize()");
    user = this;
  }
   
}
 
public class FinalizerTest {
  public static void main(String[] args) throws InterruptedException {
    User user = new User();
    user = null;
    System.gc();
    Thread.sleep(1000);
     
    user = User.user;
    System.out.println(user != null);//true
     
    user = null;
    System.gc();
    Thread.sleep(1000);
    System.out.println(user != null);//false
  }
}

- JDk9 以前的垃圾回收代码

public class Finalizer {

  @Override
  protected void finalize() throws Throwable {
    System.out.println("Finalizer-->finalize()");
  }

  public static void main(String[] args) {
    Finalizer f = new Finalizer();
    f = null;
    
    System.gc();//手动请求gc
  }
}
//输出 Finalizer-->finalize()

2:Cleaner类的使用

简介:

在Java9 以后 提供了最终类Clear来代替实现,下面看一下官方例子

package Thread;

import java.lang.ref.Cleaner;

public class CleaningExample implements AutoCloseable{

  
  private final static Cleaner CLEANER=Cleaner.create();// 创建者模式创建对象
  
  static class State implements Runnable{ // 清理对象 下面说
    State() {
      System.out.println("init");
    }
    @Override
    public void run() {
      System.out.println("close");
    }
  }
  
  private final State state;
  private final Cleaner.Cleanable  cleanable; // clearner 中的接口 实现唯一的清理方法
  
  public CleaningExample() {
    super();
    this.state = new State();
    this.cleanable=CLEANER.register(this, state); // 注册清理容器中 并且需要清理对象的引用
  }

  @Override
  public void close() throws Exception {
    cleanable.clean(); //进行清理操作
  }
  
  public static void main(String[] args) {
    while(true) {
      new CleaningExample();
    }
  }

}