标签:prot oid obj ack 应该 程序 何事 src 项目
当程序创建对象、数组等引用类型实体时,系统就会在对内存中为之分配一块内存区,对象就保存在这块内存区中,当这块内存不再被任何引用变量引用时,这块内存就变成垃圾,等待垃圾回收机制进行回收。
垃圾回收机制具有如下特点:
当一个对象失去引用后,系统何时调用它的finalize()方法对它进行资源清理,对于程序是不可控的。
程序无法精确控制Java垃圾回收的时机,但依然可以强制系统进行垃圾回收-这种强制只是通知系统进行垃圾回收,但系统是否进行垃圾回收依然不确定。大部分时候,程序强制系统垃圾回收后总会有一些效果。强制系统垃圾回收有如下两种方式:
System.gc()
Runtime.getRuntime().gc()
Object类的finalize()方法没有做任何事情,子类可以选择重写,如下:
protected void finalize() throws Throwable { }
下面我重写finalize()方法,使一个没被应用的对象重新被引用,变成可达状态。
/**
* Created by SqMax on 2018/5/12.
*/
public class FinalizeTest {
private static FinalizeTest ft;
public void info(){
System.out.println("测试方法");
}
@Override
protected void finalize() throws Throwable {
System.out.println("让变量引用该对象,使其变为可达状态");
ft=this;
}
public static void main(String[] args) {
// 该对象没有任何引用变量引用,处于可恢复状态
new FinalizeTest();
System.gc();
// Runtime.getRuntime().gc();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ft.info();
}
}
上面我们调用System.gc()方法后,还让当前线程休眠了1秒钟,因为垃圾回收机制也是一个线程,我们通知垃圾回收机制回收垃圾后,垃圾回收线程还是和main线程争夺CPU资源,所以让main线程休眠,这样垃圾回收线程就会通知没被引用的对象调用finalize()方法,是我们的ft变量引用这个对象。
执行结果如下:
让变量引用该对象,使其变为可达状态
测试方法
finalize方法有如下4个特点:
public class FinalizeTest {
private static FinalizeTest ft;
public void info(){
System.out.println("测试方法");
}
@Override
protected void finalize() throws Throwable {
System.out.println("正在进行垃圾回收....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("让变量引用该对象,使其变为可达状态");
ft=this;
}
public static void main(String[] args) {
// 该对象没有任何引用变量引用,处于可恢复状态
new FinalizeTest();
System.gc();
}
}
执行结果如下:
正在进行垃圾回收....
可以看到finalize()方法还没运行完,程序就结束了。
由于finalize()方法并不一定会被执行,而且不一定会执行完,因此如果清理某个类里打开的资源,则不要放在finalize()方法里进行清理,而应该在finally异常处理的finally块里清理。
目前还没有在项目中遇到该知识点的应用,以后遇到在补充.........
标签:prot oid obj ack 应该 程序 何事 src 项目
原文地址:https://www.cnblogs.com/sqmax/p/9045394.html