Android服务活页夹泄漏?

时间:2013-08-18 13:13:05

标签: android memory service memory-leaks android-service

我最近遇到了一个奇怪的记忆问题。每次我启动MyActivity(启动MyService)时,我的应用程序的内存使用量都会增加。因此,在启动和完成MyActivity几次后,我的应用程序内存不足。我在启动和完成两次MyActivity后进行了堆转储。我发现在内存中有2个MyService实例。在我做了“传入参考”之后 - > 'gc roots的路径'我得到了以下行(在两个实例上):

  

com ..... MyService @ 0x42746880

     
    

- >这个$ 0 com ..... MyService $ MyServiceBinder @ 42746928 Native Stack

  

我的代码与此类似:

public class MyService extends Service {

    ...

    public class MyServiceBinder extends Binder{
        MyService getService(){
            return MyService.this;
        }
    }

}

public class MyActivity extends Activity{

    private MyService service;

    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        launchService(savedInstanceState==null); //start MyService
    }

    ...

    @Override
    protected void onStart(){
        super.onStart();
        if(clientService == null)
            getApplicationContext().bindService(new Intent(this, MyService.class), connection, Context.BIND_NOT_FOREGROUND);
    }

    @Override
    protected void onStop(){
        super.onStop();
        if(clientService != null)
            getApplicationContext().unbindService(connection);
    }

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

    @Override
    protected void onBackPressed(){
        service.destroyService();  //stops MyService ->calls stopSelf inside MyService
        finish();
    }

private LocalServiceConnection connection = new LocalServiceConnection(this);

private static class LocalServiceConnection implements ServiceConnection{

        private final WeakReference<MyActivity> parent;

        private MyActivity activity;

        private MyServiceBinder binder;

public LocalServiceConnection(MyActivity parent){
    this.parent = new WeakReference<MyActivity>(parent);
        }

@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
            activity = parent.get();
            if(activity==null)
                return;
            binder = (MyServiceBinder) arg1;
            activity.service = binder.getService();
            ...
            activity = null;

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            activity = parent.get();
            binder = null;
            if(activity==null)
                return;
            activity.service = null;
            activity = null;
        }

    }
}

我不完全确定MyServiceBinder中对MyService的引用是否是泄漏的来源。那么我的代码可能会泄漏吗?

thx&amp; re骂

编辑:

private void launchService(boolean isFirst){
    if(service == null){
        if(isFirst)
            startService(new Intent(this, MyService.class);
    }
}

如果我“正常”关闭MyActivity,则服务停止,因此onDestroy之前会调用onServiceDisconnect - &gt; unbindService未被调用

EDIT2:

我再次进行了一些堆转储并通过ddms强制GC(导致GC)。我发现MyService,MyServiceBinder和LocalServiceConnection无法收集垃圾,因为它们仍在内存中,而所有其他实例都已释放。 MyService和LocalServiceConnection具有对MyServiceBinder对象的生动引用。 MyServiceBinder似乎没有gc root的路径。问题是为什么这个Binder对象不会被垃圾收集??? 是不是MyServiceBinder引用了MyService,而MyService又引用了MyServiceBinder?也许 - 如果确实存在这种循环 - 因此MyServiceBinder对象无法释放??

4 个答案:

答案 0 :(得分:1)

因此,我将Binder类作为一个独立的类,使用WeakReference服务。这并没有解决binder和serviceConnection对象的问题(它们仍然没有收集垃圾),但收集了“巨大的”服务对象..

答案 1 :(得分:0)

onCreate()检查服务中以这种方式为null,然后拨打launchService()

if (service == null){
   launchService();
} 

并在你的onDestroy()做同样的事;检查它是否为空,然后调用destroyService()

if (service !=null){
    destroyService();
}

答案 2 :(得分:0)

确保你在onPause方法中取消绑定服务:

绑定服务:

 @Override
  protected void onResume() {
    super.onResume();
    bindService();
  }

取消绑定服务

 @Override
  protected void onPause() {
    super.onPause();
    unbindService();
  }

答案 3 :(得分:0)

我看到您的服务被标记为private,您是否有任何该服务的getter方法可供其他类使用?如果这样做,您应该检查使用getter方法的位置。如果另一个类保持对服务的引用,它将不会获得gc'd。 Android中的一个大问题是将Activity的引用传递给其他类。如果你这样做,而另一个类保持对Activity的引用,它就不会被gc'd。由于看起来服务,绑定器和LocalServiceConnection都在Activity中,因此如果未发布对Activity的引用,那么它们都不会被gc'd。