Java - Object#finalize在JDK9中被标记废弃了!
时间:2022年12月6日01:34:10
 目录:
 ① 为什么要废弃?
 ② 废弃后,使用什么方式主动监测对象是否被回收?
一、为什么要废弃?
⚡注意:废弃≠移除

 
二、可以使用什么方法检测对象被回收呢?(使用Cleaner✔️)
- 可参考源码:DirectByteBuffer⚡⚡⚡ 
  
- import jdk.internal.ref.Cleaner;
 - –add-opens java.base/jdk.internal.ref=ALL-UNNAMED → 请继续阅读【三】,将会使用另一个Cleaner🚀
 
 
Cleaner使用示例:
import java.util.concurrent.TimeUnit;
public class CleanerTest {
    public static void main(String[] args) {
        User user1 = new User();
        User user2 = new User();
        System.out.println(user1);
        System.out.println(user2);
        System.gc();
        user1 = user2 = null;
        System.gc();
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { throw new RuntimeException(e); }
    }
}
或者
public class CleanerTest {
    public static void main(String[] args) {
        try (
                User user1 = new User();
                User user2 = new User();
        ) {
            System.out.println(user1);
            System.out.println(user2);
        }
    }
}
 
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import jdk.internal.ref.Cleaner;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Closeable;
@EqualsAndHashCode
public class User implements Closeable {
    private final Cleaner cleaner;
    private final _User user;
    public User() {
        user = new _User();
        cleaner = Cleaner.create(this, user);
    }
    @Override
    public String toString() {
        return user.toString();
    }
    @Override
    public void close() {
        cleaner.clean();
    }
    @EqualsAndHashCode
    @ToString
    private static class _User implements Runnable {
        private final String id;
        public _User() {
            id = IdWorker.get32UUID();
        }
        @Override
        public void run() {
            System.out.printf("哦不! 我(%s)要被回收了!%n", id);
        }
    }
}
 
三、两个Cleaner!(推荐使用 java.lang.ref.Cleaner + Closeable)

 
1.使用Cleaner示例(推荐):
import java.util.concurrent.TimeUnit;
public class CleanerTest {
    public static void main(String[] args) {
        User user1 = new User();
        User user2 = new User();
        System.out.println(user1);
        System.out.println(user2);
        System.gc();
        user1 = user2 = null;
        System.gc();
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { throw new RuntimeException(e); }
    }
}
 
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.lang.ref.Cleaner;
@EqualsAndHashCode
public class User {
    private final String id;
    private final Cleaner cleaner = Cleaner.create();
    private final Cleaner.Cleanable cleanable;
    public User() {
        this.id = IdWorker.get32UUID();
        cleanable = cleaner.register(this, new State());
    }
    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                '}';
    }
    @EqualsAndHashCode
    @ToString
    private static class State implements Runnable {
        public State() {
            System.out.println("[构造中...]: 这里一般通过参数获取堆外内存地址等信息。");
        }
        @Override
        public void run() {
            System.out.println("[回收中...]:这里一般根据堆外内存地址等信息,完成堆外内存释放。");
        }
    }
}
 
↓
 官方还推荐将要特定被回收的类实现Closeable接口,用于资源自动回收
 ↓
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Closeable;
import java.lang.ref.Cleaner;
@EqualsAndHashCode
public class User implements Closeable {
    private final String id;
    private final Cleaner cleaner = Cleaner.create();
    private final Cleaner.Cleanable cleanable;
    public User() {
        this.id = IdWorker.get32UUID();
        cleanable = cleaner.register(this, new State());
    }
    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                '}';
    }
    @Override
    public void close() {
        // Cleaner.Cleanable
        cleanable.clean();
    }
    @EqualsAndHashCode
    @ToString
    private static class State implements Runnable {
        public State() {
            System.out.println("[构造中...]: 这里一般通过参数获取堆外内存地址等信息。");
        }
        @Override
        public void run() {
            System.out.println("[回收中...]:这里一般根据堆外内存地址等信息,完成堆外内存释放。");
        }
    }
}
 
public class CleanerTest {
    public static void main(String[] args) {
        try (
                User user1 = new User();
                User user2 = new User();
        ) {
            System.out.println(user1);
            System.out.println(user2);
        }
    }
}
 
2. 结果测试




















