我最近遇到了一个奇怪的记忆问题。每次我启动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对象无法释放??
答案 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。