误区纠正:关于单例模式的内存分析
作者:网络转载 发布时间:[ 2013/4/25 10:37:16 ] 推荐标签:
小菜近在读《Java与模式》一书时,发现关于单例模式的章节中有这样一段话:
作者想表达的大意为:为了实现某个对象能够持久在内存中,以供程序在整个运行周期都可以访问,可以让对象的某个成员变量持有一个指向自身的引用,来避免被回收。
成员变量想要被清空,需要等待对象被释放,而对象被释放需要没有引用指向它,此时成员变量恰恰指向了对象本身,这看起来很不错,形成了一个循环。
但实际上,这种说法是不准确的,容易让读者产生误解。
请看下边这段代码:
package com.cnblogs.test;
public class SingletonTest {
public static void main(String[] args) {
//调用测试方法
test();
//通知jvm回收无用资源
System.gc();
System.out.println("main finalize ...");
}
//测试方法
public static void test(){
//创建A类的对象
A a = new A();
//让对象的成员变量指向其自身
a._a=a;
}
}
class A{
//定义一个成员变量,用来保存对象本身
public A _a = null;
//对象被销毁时执行的方法
protected void finalize() throws Throwable {
System.out.println("A finalize ...");
}
}
简单说明一下:
当在main方法中调用test方法时,test方法会创建一个A类的实例a,同时把实例a的堆区地址放在实例a的成员变量_a中,也是在模拟成员变量持有指向自身对象的引用。
当以上步骤执行完成后,test方法结束, 由于a是局部变量,保存在方法栈中,会被立即释放,不再指向A类的实例,但是我们刚刚完成了“自引用”,根据上边的理论,有引用指向A类的实例,实例便不会被释放,因此上边程序的输出结果是“main 方法执行完毕...”。
遗憾的是,结果并不是这样,真实的输出结果为:“main 方法执行完毕...A 被回收...”。
为什么会这样?听听小菜的解释。
单例模式创建的对象能够一直存在于内存中不被释放,并不只是由于持有一个自身的引用,本质是因为这个引用是静态的!也是说,如果成员变量是非静态的,它持有一个自身的引用,那么这个对象还是会被回收。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11