下面举一个Android中的例子

public class HomeActivity extends Activity {

public static Drawable mBackground_img;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

TextView tv = new TextView(this);

tv.setGravity(Gravity.CENTER_HORIZONTAL);

tv.setTextSize(20);

if(mBackground_img==null){

mBackground_img = getApplicationContext().getResources().getDrawable(R.drawable.background);

}

tv.setBackgroundDrawable(mBackground_img);

setContentView(tv);

}

}

执行流程:类加载器将HomeActivity这个类的各种信息加载到方法区,然后定位到该类的onCreate方法执行,该线程为这个方法分配一个栈帧,压入到该线程的栈中(也就是在该线程的栈中为这个方法分配一块内存),然后执行这个方法。执行TextView tv = new TextView(this);首先在栈中为tv分配存储空间,然后在堆内存中创建一个TextView对象。TextView被实例化了,他的属性也会被初始化,TextView的基本变量和引用变量都被存储到栈中,并且在堆内存中分配存储空间,创建对象。执行完这行代码,tv保留了一个对当前Activity的引用。mBackground_img是一个静态变量,他被存储在方法区(我认为他所指向的的对象被存储在堆内存)。tv.setBackgroundDrawable(mBackground_img);

这行的代码能够让mBackground_img保留对tv的引用(查看Drawable的setCallBack方法)。这样就形成了这样一条链,怎么解释我还不清楚

当横竖屏切换的时候,TextView 的实例对象(tv指向的对象)会不会GC回收?

当onCreate方法执行完后,该方法出栈,那么tv肯定会被释放,但是tv指向的实例对象仍旧被mBackground_img引用,mBackground_img是个全局静态变量,他不会被释放,因此tv所指向的TextView对象不会被GC回收,同时TextView保留了该activity的引用,这样,当横竖屏切换的时候,该activity也不会被GC回收。这是想当然的情况,当横竖屏切换的时候,会重新给mBackground_img赋值,也就是他不会指向之前的对象了,那么这个时候就没有任何引用指向drawable对象了,那么按理说这个时候就能GC了,通过实验结合Memory Analizer工具检测,发生了内存泄露,不知道是为什么?

一直觉着内存泄露这个问题很抽象,不甚理解,欢迎大家指导,帮助小弟解决这个问题

 

补充:

  问题1:TextView的实例化对象存储在堆内存,那么他的属性的值存储在什么地方,例如上述的mBackground_img对象,也是按照引用存储在栈内存,对象存储在堆内存中吗?我看了一些资料,有这么两种说法,一种是实例化对象的各种属性都存储在heap内存,不管是基本类型的属性,还是引用类型的属性,类似于对象实例化那样;还有一种说法是依旧按照引用存储在栈内存,对象存储在堆内存,基本类型变量存储在栈内存的原则,请大家指教


posted on 2010-12-14 11:22  Android火鸟  阅读(880)  评论(0编辑  收藏  举报