在说明finalize()的用法之前要树立有关于java垃圾回收器几个观点:
finalize()的功能 : 一旦垃圾回收器准备释放对象所占的内存空间, 如果对象覆盖了finalize()并且函数体内不能是空的, 就会首先调用对象的finalize(), 然后在下一次垃圾回收动作发生的时候真正收回对象所占的空间.
finalize()有一个特点就是: JVM始终只调用一次. 无论这个对象被垃圾回收器标记为什么状态, finalize()始终只调用一次. 但是程序员在代码中主动调用的不记录在这之内.
如果需要释放对象的父类所占的资源, 那么就必须自己手动构造finalize调用链
1 2 3 4 | protected void finalize() throws Throwable { super .finalize(); } |
finalize()主要使用的方面:
尽管finalize()可以主动调用, 但是最好不要主动调用, 因为在代码中主动调用之后, 如果JVM再次调用, 由于之前的调用已经释放过资源了,所以二次释放资源就有可能出现导致出现空指针等异常, 而恰好这些异常是没有被捕获的, 那么就造成对象处于被破坏的状态, 导致该对象所占用的某一部分资源无法被回收而浪费.
尽量避免使用finalize():
finalize执行的生命周期:
注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法
对象重生的代码1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | class C { static A a; } class A { B b; public A(B b) { this .b = b; } @Override public void finalize() { System.out.println( "A finalize" ); C.a = this ; } } class B { String name; int age; public B(String name, int age) { this .name = name; this .age = age; } @Override public void finalize() { System.out.println( "B finalize" ); } @Override public String toString() { return name + " is " + age; } } public class Main { public static void main(String[] args) throws Exception { A a = new A( new B( "allen" , 20 )); a = null ; System.gc(); Thread.sleep( 5000 ); System.out.println(C.a.b); } } |
我的理解:为方便起见, 把a,b两个变量所指的内存空间就叫做a和b
对象重生的代码2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public class GC { public static GC SAVE_HOOK = null ; public static void main(String[] args) throws InterruptedException, Throwable { SAVE_HOOK = new GC(); SAVE_HOOK = null ; System.gc(); Thread.sleep( 500 ); if ( null != SAVE_HOOK) //此时对象应该处于(reachable, finalized)状态 { System.out.println( "Yes , I am still alive" ); } else { System.out.println( "No , I am dead" ); } SAVE_HOOK = null ; System.gc(); Thread.sleep( 500 ); if ( null != SAVE_HOOK) { System.out.println( "Yes , I am still alive" ); } else { System.out.println( "No , I am dead" ); } } @Override protected void finalize() throws Throwable { super .finalize(); System.out.println( "execute method finalize()" ); SAVE_HOOK = this ; } } |