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. On Thu, Aug 30, 2012 at 2:42 PM, Dave Smith <dasmith1...@gmail.com> wrote: > I have an application that communicates with a Service in a remote > process using the Messengerinterface. Here is the basic architecture of > how things are set up: > > - The application generates several "Operation" objects that require > access to the service. > - Each "Operation" contains a Handler wrapped in a Messenger used as a > callback receive the response data back from the Service > - When the operation executes, it wraps its Messenger into an Intent and > calls startService() to pass the message to the remote service > - The remote service does some work based on the parameters of the > Intent and then returns the response by sending a Message to the > Messenger for that operation. > > Here is the basic code present in the operation: > > 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); > } > > And a basic snippet of how the service is structured: > > 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); > } > } > > This all works fantastically well. I can send tons of operations from > several different applications to the same service and they all process and > send their response to just the right place. However... > > I noticed that if the application ran long enough and with enough activity > it would crash with anOutOfMemoryError. Upon looking at the HPROF data in > MAT, I noticed that all these operations where staying in memory, and they > were held hostage from the Garbage Collector because of theMessenger. > Apparently, the Messenger instance is creating a long-term native > connection to Binder that counts as a GC Root, which is keeping each > "Operation" object in memory indefinitely. > > [image: MAT Trace Example] > > Does anyone know if there is a way to clear or disable the Messenger when > the "Operation" is over so it doesn't create this memory leak? > > Is there perhaps a better way to implement the IPC to the Servicein the > same fashion, so that multiple disparate objects can make a request and get > a result asynchronously? I'm not convinced that just switching to using a > bound service implementation will solve this issue as I would will need the > Messenger to process the callback. > > -- > You received this message because you are subscribed to the Google > Groups "Android Developers" group. > To post to this group, send email to android-developers@googlegroups.com > To unsubscribe from this group, send email to > android-developers+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en -- Dianne Hackborn Android framework engineer hack...@android.com Note: please don't send private questions to me, as I don't have time to provide private support, and so won't reply to such e-mails. All such questions should be posted on public forums, where I and others can see and answer them. -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en