为成品后Thread对象不被垃圾收集(Thread objects not garbage coll

2019-07-30 14:13发布

我注意到,我的应用程序正在泄漏内存。 这可以在DDMS中可以看出,我得到了一个OutOfMemoryError异常。

我找到了泄漏源。 一个活动的有在后台运行一个线程。 该线程停止onDestroy() 它完成运行,因为它可以在DDMS中可以看出。

现在,如果线程启动,发生泄漏,活动是不是垃圾被破坏后收集的,因为它是由线程引用。 如果线程不会启动,一切正常。

下面是简单的例子证明这一点:

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    volatile boolean finished = false;
    byte[] memoryEater = new byte[4 * 1024 * 1024];

    Thread thread = new Thread(new Runnable() {

        @Override
        public void run() {
            while (!finished) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            Log.d(getClass().getName(), "Thread finished");
        }
    });

    @Override
    protected void onDestroy() {
        super.onDestroy();
        finished = true;
    }

    public void startActivity(View view) {
        startActivity(new Intent(this, MainActivity.class));
    }

    public void startThread(View view) {
        thread.start();
    }
}

添加一个按钮,用于启动新的活动和一个用于启动一个线程。 开始新的活动。 回去之后,内存只能如果线程尚未启动清洗。

什么是这种行为的原因是什么?

Answer 1:

我刚刚想出了这个同样的问题。

托马斯,你是在正确的轨道上。 有一个在DDMS NO错误并且在你的程序没有内存泄漏。

真正的问题是你在调试模式下运行程序(在Eclipse中)。 以某种方式时的Android在调试模式下运行时,线程是不是run()方法已经退出即使垃圾收集。 我想这可能是Android的需要扶住线程对某些调试功能来工作。

但是,如果你运行你在运行模式下(Eclipse的仍然下)应用,线程垃圾收集发生。 该线程将被完全释放,你的活动将完全释放。



Answer 2:

我一直在调查我发现什么是真正suprising。 似乎没有真正的内存泄漏。 这种事只有当应用程序是在调试DDMS模式。

DDMS似乎以某种方式持有这些成品胎面引用,防止它们成为GC-ED。 当我断开手机与重新连接,我可以看到所有的“泄露”的资源已被释放。

它看起来像在DDMS的错误。



Answer 3:

由线程使用的匿名运行的类将不得不活性的参考(“本”)。 作为该线程的活动引用,并在该线程可运行引用活动中,GC绝不会收集其一。

尝试做更多的东西是这样的:

private static RunnableClass implements Runnable
{
    @Override
    public void run() {
        while (!finished) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        Log.d(getClass().getName(), "Thread finished");
    }
});

Thread thread = new Thread(new RunnableClass());


Answer 4:

当“背”被按下或任何其他意图被发送到从堆栈的顶部移除它的活动不被破坏。 我不认为你重写的onDestroy()方法被称为有史以来直到你的Android操作系统运行的内存。 从文档一个可以提取:

正如有关活动的生命周期中的以下部分讨论的,Android系统为您管理活动的生活,所以你并不需要完成自己的活动。 调用这些方法可以在预期的用户体验产生不利影响,应仅用于当你绝对不希望用户返回到这一活动实例。

通常情况下,每一个活动实例周围铺设在内存初始创建后,通过去onStart()...onStop()循环而不被破坏。 实施onStop()并调用finish()在它MainActivity与线程被释放,因此收集垃圾。

更新 :上面的说法是不正确的。 基于对这一问题提供的代码,没有理由的活动不应该是GC-ED。



文章来源: Thread objects not garbage collected after being finished