什么是finalize()?

finalize()方法是Object的一个方法,JVM在GC的时候会调用这个方法,一般当对象不可达GC就会回收这个对象,但是如果我们可以重写这个方法且这方法体不是空方法,那么这个对象则不会被回收,这之后JVM还会监测一次该对象是否可达,如果不可达则会最终回收,要注意的是finalize()方法只会被执行一次,也就是说对象只有这一次补救机会。

以下为Finalize的测试代码

public class FinalizeCase {
    private static Block holder = null;
    public static void main(String[] args) throws Exception {
        holder = new Block();
        holder = null;
        System.gc();
        Thread.sleep(5000);
        System.gc();
        //System.in.read();
    }
    static class Block {
        byte[] _200M = new byte[200*1024*1024];
        protected void finalize() throws Throwable {
            //finalize只会调用一次,这里不是空方法
            FinalizeCase.dosomething();
        }
    }
    static void dosomething(){
        System.out.println("阻止回收");
    }
}

GC回收信息:

[GC (System.gc()) [PSYoungGen: 2621K->528K(76288K)] 207421K->205336K(456704K), 0.0018733 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 528K->0K(76288K)] [ParOldGen: 204808K->205200K(380416K)] 205336K->205200K(456704K), [Metaspace: 3095K->3095K(1056768K)], 0.0083431 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC (System.gc()) [PSYoungGen: 3937K->416K(76288K)] 209137K->205624K(456704K), 0.0048387 secs] [Times: user=0.04 sys=0.00, real=0.01 secs] 
[Full GC (System.gc()) [PSYoungGen: 416K->0K(76288K)] [ParOldGen: 205208K->719K(380416K)] 205624K->719K(456704K), [Metaspace: 3597K->3597K(1056768K)], 0.0080669 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 76288K, used 655K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)
  eden space 65536K, 3% used [0x000000076ab00000,0x000000076aceb9e0,0x000000076eb00000)
  from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)
  to   space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)
 ParOldGen       total 380416K, used 719K [0x00000006c0000000, 0x00000006d7380000, 0x000000076ab00000)
  object space 380416K, 0% used [0x00000006c0000000,0x00000006c00b3ee8,0x00000006d7380000)
 Metaspace       used 3603K, capacity 4540K, committed 4864K, reserved 1056768K
  class space    used 401K, capacity 428K, committed 512K, reserved 1048576K

Process finished with exit code 0

如上,第一次200M的空间没有被回收,第二次回收成功

那么一般用来做什么?

比如说回收堆外内存,当我们使用Unsafe类来分配(Allocate direct memory)堆外空间以后,对象被回收的同时,这块内存区域是不会被JVM回收的,我们可以重写Finalize方法,在其中调用Unsafe.freeMemory来回收。