android– 远程服务的Messenger导致内存泄漏

android– 远程服务的Messenger导致内存泄漏,第1张

概述我有一个应用程序使用Messenger接口在远程进程中与服务进行通信.以下是设置方式的基本架构:>应用程序生成几个需要访问服务的“ *** 作”对象.>每个“ *** 作”都包含一个包含在Messenger中的Handler,用于从服务接收响应数据>当 *** 作执行时,它将Messenger包装为Intent并调用startService()

我有一个应用程序使用Messenger接口在远程进程中与服务进行通信.以下是设置方式的基本架构:

>应用程序生成几个需要访问服务的“ *** 作”对象.
>每个“ *** 作”都包含一个包含在Messenger中的Handler,用于从服务接收响应数据
>当 *** 作执行时,它将Messenger包装为Intent并调用startService()将消息传递给远程服务
>远程服务根据Intent的参数执行某些 *** 作,然后通过向Messenger发送消息来返回响应.

以下是 *** 作中的基本代码:

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);}

以及如何构建服务的片段(它基本上是一个在队列为空时不会关闭的IntentService):

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);    }}

这一切都非常好.我可以将来自多个不同应用程序的大量 *** 作发送到同一个服务,他们都会处理并将响应发送到正确的位置.然而…

我注意到如果应用程序运行得足够长并且有足够的活动,它会因OutOfMemoryError而崩溃.在MAT中查看HPROF数据时,我注意到所有这些 *** 作都停留在内存中,并且由于Messenger而被垃圾收集器挟持.显然,Messenger实例正在创建一个与Binder的长期本机连接,它被视为GC Root,它将每个“Operation”对象无限期地保存在内存中.

有没有人知道当“ *** 作”结束时是否有办法清除或禁用Messenger,这样就不会造成内存泄漏?是否有另一种方法可以以相同的方式将IPC实现到服务中,以便多个不同的对象可以发出请求并异步获得结果?

提前致谢!

解决方法:

感谢Dianne Hackborn在AndroID团队中提供的一些非常有用的见解,问题是因为远程服务进程还没有Garbage收集它的Messenger实例,实际上,直到那时为止,实例中将实例保存在应用程序的进程中.

这是她回复的内容:

It is true that sending a messenger across processes will require holding a GREF on it for the other process to communicate with it. barring BUGs (which have happened but I am not sure if in any released platform versions), the GREF will be released when the other process itself no longer holds a reference on this. When we are talking about things in Dalvik “no longer holds a reference” generally means “the other sIDe has garbage collected the Java proxy object.”

What this means is that when you throw a Messenger (or any IBinder object) across to another process, the Dalvik VM in your own process can no longer manage the memory of that object itself and is dependent on all remote objects releasing it until it can be released locally. And this will include all objects that the IBinder has any references to as well.

A common pattern to deal with this is to use a WeakReference in your IBinder/Messenger that holds the references to the rest of your objects that it will access. This allows your local garbage collector to clean up all of those other objects (which may be quite heavy, holding big things like bitmaps and such) even though a remote process still has a reference on your IBinder. Of course if you do this, there needs to be something else holding a reference on these other objects until they are no longer needed, or else the garbage collector Could clean them up before they are no longer needed.

Something else I would recommend is to not do a design where you instantiate Messenger objects for each IPC you do. Create one Messenger that you pass in to each IPC call. Otherwise you can generate a lot of remoted objects that are being kept around due to other processes continuing to hold references because the other sIDe is not aggressively garbage collecting since all the objects it is creating due to these calls are small.

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

总结

以上是内存溢出为你收集整理的android – 远程服务的Messenger导致内存泄漏全部内容,希望文章能够帮你解决android – 远程服务的Messenger导致内存泄漏所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1097884.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-28
下一篇 2022-05-28

发表评论

登录后才能评论

评论列表(0条)

保存