Messenger to Remote Service Causing Memory Leak

后端 未结 2 863
再見小時候
再見小時候 2021-01-03 14:39

I have an application that communicates with a Service in a remote process using the Messenger interface. Here is the basic architecture of how th

相关标签:
2条回答
  • 2021-01-03 14:45

    Thanks to some very helpful insight from Dianne Hackborn on the Android team, the issue is because the remote service process has not yet Garbage Collected it's instance of the Messenger which, in effect, held the instances in the application's process hostage until that time.

    This is the text of her reply:

    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.

    More Info: https://groups.google.com/d/msg/android-developers/aK2o1W2xrMU/Z0-QujnU3wUJ

    0 讨论(0)
  • 2021-01-03 15:03

    I am not sure if this is the best way since, even if Activity is in the background you will get the message from Service.

    I think you should bind to the service and register a messenger to the service as soon as Service is connected. And then unregister the messenger when you disconnect.

    Check ExportVcardActivity in AOSP. It is following something along these lines.

    0 讨论(0)
提交回复
热议问题