Java9以后的垃圾回收

  • 2019 年 10 月 14 日
  • 筆記

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();          }      }    }

 

上面 看出:

 

  • Cleaner 是最终类 不能被重写, 内部方法基本以静态方法提供  掌握例子上面的方法即可

 重点指出

 static class State implements Runnable

  •  如果直接在类中直接定义实现, 必须提供一个静态内部类 (强制),否者不能进行回收   原因(: 普通内部类 局部内部类 对于外部类有依赖(引用),无法真正实现内存的释放 )
  •   可以选择直接定义外部类 (较为复杂,需要传递清理引用  Cleanable)

什么时候被回收?

  • * 1. 注册的Object处于幻象引用状态

  • * 2. 显式调用 clean 方法

实际例子(模版)

public class CleaningExample extends Thread implements AutoCloseable {      private final static Cleaner CLEANER = Cleaner.create();      private final State state;      private final Cleaner.Cleanable cleanable;        public CleaningExample() {          this.state = new State();          this.cleanable = CLEANER.register(this, state);      }        @Override      public void close() throws Exception {          cleanable.clean();      }        @SuppressWarnings("resource")      public static void main(String[] args) {          while (true) {              CleaningExample example = new CleaningExample();          }      }      // 模拟业务请求      @Override      public void run() {          System.out.println("数据库 海量 查询请求 ................");      }      // 清理模版      class State implements Runnable {          State() {              System.out.println("<--- init --->");          }          @Override          public void run() {              System.out.println("<--- close --->");          }      }  }

 

实现基础

    /**       * Heads of a CleanableList for each reference type.       */      final PhantomCleanable<?> phantomCleanableList;        final WeakCleanable<?> weakCleanableList;        final SoftCleanable<?> softCleanableList;        // The ReferenceQueue of pending cleaning actions      final ReferenceQueue<Object> queue;

 

在CleanerImpl 类进行clearner类的最终实现,看以看到定义的这些个字段,基本上明确了 他的基本原理