我有一个使用Service接口(interface)在远程过程中与Messenger通信的应用程序。这是事物设置的基本架构:

  • 该应用程序生成几个需要访问服务的“Operation”对象。
  • 每个“操作”都包含一个Handler,该Messenger包装在Service中,该Messenger用于接收来自Intent的响应数据
  • 执行该操作时,它将startService()包装为Intent,然后调用Message将消息传递给远程服务
  • 远程服务根据Messenger的参数进行一些工作,然后通过向该操作的IntentService发送OutOfMemoryError来返回响应。

  • 这是该操作中存在的基本代码:
    public class SessionOperation {
    
        /* ... */
    
        public void runOperation() {
            Intent serviceIntent = new Intent(SERVICE_ACTION);
            /* Add some other extras specific to each operation */
            serviceIntent.putExtra(Intent.EXTRA_EMAIL, replyMessenger);
    
            context.startService(serviceIntent);
        }
    
        private Handler mAckHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                //Process the service's response
            }
        };
        protected Messenger replyMessenger = new Messenger(mAckHandler);
    }
    

    以及如何构造服务的代码段(基本上是一个Messenger,当队列为空时它不会关闭):
    public class WorkService extends Service {
        private ServiceHandler mServiceHandler;
    
        private final class ServiceHandler extends Handler {
            public ServiceHandler(Looper looper) {
                super(looper);
            }
    
            @Override
            public void handleMessage(Message msg) {
                onHandleIntent((Intent)msg.obj);
            }
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            //If intent has a message, queue it up
            Message msg = mServiceHandler.obtainMessage();
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
    
            return START_STICKY;
        }
    
        private void onHandleIntent(Intent intent) {
            Messenger replyTarget = intent.getParcelableExtra(Intent.EXTRA_EMAIL);
    
            /* Do some work */
    
            Message delivery = Message.obtain(...);
            replyTarget.send(delivery);
        }
    }
    

    所有这些都非常出色。我可以将大量操作从几个不同的应用程序发送到同一服务,它们全部处理并将响应发送到正确的位置。然而...

    我注意到,如果应用程序运行了足够长时间且具有足够的 Activity 性,它将因Messenger崩溃。在MAT中查看HPROF数据时,我注意到所有这些操作都保留在内存中,由于Messenger,它们被垃圾收集器作为人质。显然,Service实例正在创建与Binder的长期本地连接,该连接被视为GC根,从而无限期地将每个“Operation”对象保留在内存中。

    有谁知道“操作”结束后是否有清除或禁用ojit_code的方法,从而不会造成此内存泄漏?是否可能存在另一种以相同方式将IPC实现到ojit_code的方法,以便多个不同的对象可以发出请求并异步获取结果?

    提前致谢!

    最佳答案

    感谢Android团队的Dianne Hackborn的一些非常有帮助的见解,该问题是因为远程服务进程尚未垃圾收集它的Messenger实例,实际上该实例一直将实例保留在应用程序的进程中。
    这是她的回复文本:

    更多信息:
    https://groups.google.com/d/msg/android-developers/aK2o1W2xrMU/Z0-QujnU3wUJ

    关于android - Messenger到远程服务导致内存泄漏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12204740/

    10-11 09:21