深入理解 finalize
深入理解 finalize
1.方法说明:
调用 gc 方法暗示着 Java
虚拟机做了一些努力来回收未用对象,以便能够快速地重用这些对象当前占用的内存。当控制权从方法调用中返回时,虚拟机已经尽最大努力从所有丢弃的对象中回收了空间。
调用这个方法后,垃圾回收器将回收 novel 引用所指向的对象(即 new Book()建立的对象) ,在试图回收时会先执行finalize() 方法;然后暂时停止回收,第二次回收时,才会执行清理对象回收空间的动作
finalize() 是Object中的方法,我们自己创建的类全都是默认继承自这个类。
调用 gc 方法暗示着 Java
虚拟机做了一些努力来回收未用对象,以便能够快速地重用这些对象当前占用的内存。当控制权从方法调用中返回时,虚拟机已经尽最大努力从所有丢弃的对象中回收了空间。
调用这个方法后,垃圾回收器将回收 novel 引用所指向的对象(即 new Book()建立的对象) ,在试图回收时会先执行finalize() 方法;然后暂时停止回收,第二次回收时,才会执行清理对象回收空间的动作
finalize() 是Object中的方法,我们自己创建的类全都是默认继承自这个类。
2 工作原理:
由于java虚拟机只知道释放那些通过new的方式分配的内存
但是你的对象并非是通过new而获得的一块“特殊”的内存。为了解决
这一问题,java允许在类中定义一个finalize()方法
其工作原理如下:
一旦垃圾回收准备释放对象占用的内存,将首先调用finalize()方法,
并且在下一次垃圾回收动作发生的时候才会真正的回收对象所占用的内存,
使用finalize()是为了在垃圾回收时候做一些重要的清理工作。
需要留意的是:只要程序的存储空间没有用尽,对象的占用空间也就
的不到释放。
也就是说垃圾回收针对的是程序不再使用的内存。
finalize()使用在这种情况:“使用本地方法”分配内存,
例如使用malloc()分配存储空间,除非调用free()否则内存空间将得不到
释放,从而内存泄露。因此free方法就应该在finalize()中用本地方法调用它。
由于java虚拟机只知道释放那些通过new的方式分配的内存
但是你的对象并非是通过new而获得的一块“特殊”的内存。为了解决
这一问题,java允许在类中定义一个finalize()方法
其工作原理如下:
一旦垃圾回收准备释放对象占用的内存,将首先调用finalize()方法,
并且在下一次垃圾回收动作发生的时候才会真正的回收对象所占用的内存,
使用finalize()是为了在垃圾回收时候做一些重要的清理工作。
需要留意的是:只要程序的存储空间没有用尽,对象的占用空间也就
的不到释放。
也就是说垃圾回收针对的是程序不再使用的内存。
finalize()使用在这种情况:“使用本地方法”分配内存,
例如使用malloc()分配存储空间,除非调用free()否则内存空间将得不到
释放,从而内存泄露。因此free方法就应该在finalize()中用本地方法调用它。
3.使用说明:
当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。
finalize 的常规协定是:当 JavaTM
虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时,将调用此方法,除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其中包括再次使此对象对其他线程可用;
不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。Object 类的 finalize 方法执行非特殊性操作;
不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。Object 类的 finalize 方法执行非特殊性操作;
它仅执行一些常规返回。Object 的子类可以重写此定义。Java 编程语言不保证哪个线程将调用某个给定对象的 finalize 方法。但可以保证在调用 finalize 时,调用
finalize 的线程将不会持有任何用户可见的同步锁定。如果 finalize 方法抛出未捕获的异常,那么该异常将被忽略,并且该对象的终结操作将终止。在启用某个对象的 finalize 方法后,将不会执行进一步操作,直到 Java 虚拟机再次确定尚
未终止的任何线程无法再通过任何方法访问此对象,其中包括由准备终止的其他对象或类执行的可能操作,在执行该操作时,对象可能被丢弃。对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。finalize 方法抛出的任何异常都会导致此对象的终结操作停止,
但可以通过其他方法忽略它。
抛出:
Throwable - 此方法抛出的 Exception
未终止的任何线程无法再通过任何方法访问此对象,其中包括由准备终止的其他对象或类执行的可能操作,在执行该操作时,对象可能被丢弃。对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。finalize 方法抛出的任何异常都会导致此对象的终结操作停止,
但可以通过其他方法忽略它。
抛出:
Throwable - 此方法抛出的 Exception
4.代码举例:
package System.gc;
public class TestGc {
public static TestGc HOOK;
package System.gc;
public class TestGc {
public static TestGc HOOK;
@Override
protected void finalize() throws Throwable {
super.finalize();
TestGc.HOOK = this;
System.out.println("finalize");
}
protected void finalize() throws Throwable {
super.finalize();
TestGc.HOOK = this;
System.out.println("finalize");
}
/*
输出结果
finalize
HOOK is alvie
HOOK is dead
*/
public static void main(String[] args) throws Exception {
HOOK = new TestGc();
HOOK = null;
System.gc();//第一次GC,符合有必要要执行finalize的条件
Thread.sleep(1000);//Finalizer线程优先级较低,所以要等一会
if (HOOK != null) {
System.out.println("HOOK is alvie");
} else {
System.out.println("HOOK is dead");
}
输出结果
finalize
HOOK is alvie
HOOK is dead
*/
public static void main(String[] args) throws Exception {
HOOK = new TestGc();
HOOK = null;
System.gc();//第一次GC,符合有必要要执行finalize的条件
Thread.sleep(1000);//Finalizer线程优先级较低,所以要等一会
if (HOOK != null) {
System.out.println("HOOK is alvie");
} else {
System.out.println("HOOK is dead");
}
HOOK = null;
System.gc();//第二次GC,因为已经执行过一次finalize,所以没有必要进行二次标记
Thread.sleep(1000);//Finalizer线程优先级较低,所以要等一会
if (HOOK != null) {
System.out.println("HOOK is alvie");
} else {
System.out.println("HOOK is dead");
}
}
System.gc();//第二次GC,因为已经执行过一次finalize,所以没有必要进行二次标记
Thread.sleep(1000);//Finalizer线程优先级较低,所以要等一会
if (HOOK != null) {
System.out.println("HOOK is alvie");
} else {
System.out.println("HOOK is dead");
}
}
}
原文链接:http://www.jxszl.com/biancheng/JAVA/446440.html