Android(java) 回收gc问题

步骤:
1、activity中,有一个成员变量,这个成员变量是一个自定义类TestInnerClass
2、这个自定义TestInnerClass,里面有个内部类InnerClass,是个Runnable接口。
3、运行这个activity,然后调用了testInnerClass.run(),线程就会在后台一直跑。然后关闭activity。

代码如下:

public class TestActivity extends Activity {

    private TestInnerClass  testInnerClass;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        testInnerClass = new TestInnerClass();
        testInnerClass.run();
    }
}


public class TestInnerClass {

    public void run(){
        InnerClass innerClass = new InnerClass();
        Thread thread = new Thread(innerClass);
        thread.start();
    }


    public class InnerClass implements Runnable{

        private Context context;

        public InnerClass() {
        }

        public InnerClass(Context context) {
            this.context = context;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(2000); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
     }

}

在此过程中,我猜测:
1、InnerClass是个内部类,在TestInnerClass的run()方法中,new了这个对象,那么TestInnerClass就会被InnerClass持有,而InnerClass这个runnable接口,又会被thread持有,因此,TestInnerClass在activity关闭之后,不会被释放。
2、由于TestInnerClass没有被释放,这时候就触及到了我的知识盲区,这个时候activity到底能不能被释放呢?gc规则的话,能否回收这个对象,要看可达性,activity是没有被其他地方强引用的,但是它的成员变量TestInnerClass又被thread持有,那activity会怎样呢?

然后我用android studio看了一下关闭activity后的内存:
图片说明

然后,对于TestInnerClass,确实存在于内存:
图片说明
图片说明

我的疑问是:
activity被回收的时候,成员变量在跟activity不同生命周期的thread中被引用。那么java的回收有没有可能存在是,实例被回收了,但是实例中的成员变量还在内存中?

https://blog.csdn.net/u013534071/article/details/80254127

首先先回答你的问题:
问题:由于TestInnerClass没有被释放,这时候就触及到了我的知识盲区,这个时候activity到底能不能被释放呢?
回答:activity对象没有被释放
问题:实例被回收了,但是实例中的成员变量还在内存中?
答案:成员变量不会还在内存中。

如果证明?
可以在

Thread.sleep(2000); 

这一行打断点,然后观察内存即可。
图片说明

TestInnerClass 是Activity的内部类,自动的它是持有外部Activity的实例对象的
所以,Activity实例不会被释放,同样的它内部的成员变量也不会被释放,
你这样写是会造成Activity这个对象的内存泄漏的

经过一段时间的探索以后,发现我这个写法testInnerClass = new TestInnerClass();  InnerClass innerClass = new InnerClass();都不是内部类的写法,只是生成了一个对象。因此不会持有外部类这个说法。因此activity能回收。而新起的线程有它自己的生命周期,因此profile能看到。