参考资料
[1]. 疯狂Java讲义(第三版) 李刚
[2]. 对象在内存中的状态,
http://blog.csdn.net/jiawei6212130/article/details/52263392
[3]. 疯狂Java笔记之Java的内存与回收,
https://www.jianshu.com/p/b6e7ba99593d
[4]. 垃圾回收与finalize,
http://blog.csdn.net/u012813201/article/details/73229007
对象在内存中的状态
/**
* 对象在内存中的状态的表达
*/
public class StatusTranfer {
public static void test()
{
// 因为被引用,AAA字符串处于可达状态
String a = new String("AAA");
// 因为被替代,AAA字符串处于可恢复状态
// 因为被引用,BBB字符串处于可达状态
a = new String("BBB");
}
public static void main(String[] args)
{
// 当该方法执行完以后,全部字符串都被销毁,处于不可达状态
test();
}
}
强制垃圾回收
强制系统垃圾回收有两种方式:
1. 调用System类的gc()静态方法:System.gc()。
2. 调用Runtime对象的gc实例方法:Runtime.getRuntime().gc()。
因为系统在回收资源的时候会调用finalize()方法。所以下面覆盖了该方法:
/**
* 测试强制回收功能
*/
public class GcTest {
/**
* 覆盖finalize方法
*/
@Override
public void finalize()
{
System.out.println("系统正在清理GcTest对象的资源...");
}
public static void main(String[] args)
{
for (int i = 0; i < 4; i++)
{
new GcTest();
// 使用下面的代码执行主动系统资源主动回收
System.gc();
Runtime.getRuntime();
}
}
}
finalize方法
finalize()方法具有如下4个特点:
1. 永远不要主动调用某个对象的finalize()方法,该方法应交给垃圾回收机制调用。
2. finalize()方法何时被调用,是否被调用具有不确定性,finalize()不一定被执行。
3. 当JVM执行可恢复对象的finalize()方法时,可能使该对象或系统中其他对象重新变成可达状态。
(4)当JVM执行finalize()方法时出现异常时,垃圾回收机制不会报告异常,程序继续执行。
下面的程序演示了如何在finalize()方法里复活自身,并可通过该程序看出垃圾回收的不确定性。
public class FinalizeTest {
private static FinalizeTest ft = null;
public void info()
{
System.out.println("测试资源清理的finalize方法");
}
public static void main(String[] args) throws Exception
{
// 创建FinalizeTest对象立即进入可恢复状态
new FinalizeTest();
// 通知系统进行垃圾回收
// 如果不通知,则会引起java.lang.NullPointerException异常
// System.gc();
// 强制垃圾回收机制调用可恢复对象的finalize()方法
Runtime.getRuntime().runFinalization();
//System.runFinalization();
ft.info();
}
@Override
public void finalize()
{
// 让tf引用到试图回收的可恢复对象,即可恢复对象重新变成可达
ft = this;
}
}
对象的软、弱和虚引用
弱引用通过WeakReference类实现。对于软引用的对象而言,当系统垃圾回收机制运行时,不管系统内存时候足够,总会回收改对象所占用的内存。
// 创建一个字符串对象
String str = new String("aaa");
// 创建一个弱引用,让此弱引用引用到"aaa"字符串
WeakReference wr = new WeakReference(str);
// 切断str引用和"aaa"字符串之间的引用
str = null;
// 取出弱引用所引用的对象
System.out.println(wr.get());
// 强制垃圾回收以后
System.gc();
System.runFinalization();
// 再次取出弱引用所引用的对象为null
System.out.println(wr.get());
虚引用的主要作用就是跟踪对象被垃圾回收的状态,程序可以通过检查与虚引用关联的引用队列中是否包含指定的虚引用,从而了解虚引用所引用的对象是否即将被回收。虚引用通过PhantomReference类实现
// 创建一个字符串对象
String str = new String("疯狂Java讲义");
// 创建一个引用队列
ReferenceQueue rq = new ReferenceQueue();
// 创建一个虚引用,让此虚引用引用到"疯狂Java讲义"字符串
PhantomReference pr = new PhantomReference (str , rq);
// 切断str引用和"疯狂Java讲义"字符串之间的引用
str = null;
// 取出虚引用所引用的对象,并不能通过虚引用获取被引用的对象,所以此处输出null
System.out.println(pr.get()); //①
// 强制垃圾回收
System.gc();
System.runFinalization();
// 垃圾回收之后,虚引用将被放入引用队列中
// 取出引用队列中最先进入队列中的引用与pr进行比较
System.out.println(rq.poll() == pr); //②