Christopher Tate 86284c60b5 Stop leaking DeathRecipient and BinderProxy instances
The native-side death recipient object holds a global reference
to the DVM-side DeathRecipient instance.  This is necessary so
that the DeathRecipient isn't GC'd early in the case when the
caller of linkToDeath() doesn't retain their own reference to
the recipient instance.

However, that global reference was never being released in
association with the delivery of the actual binderDied() event.
In that case, if the death recipient did not explicitly call
unlinkToDeath() themselves, the hard global reference was
maintained and a hard-reference cycle was perpetuated, crossing
the native <-> DVM boundary.  This was visible as a gradual
leakage of DVM-side DeathRecipient and BinderProxy instances.

The one problematic constraint is that it needs to be valid to
call unlinkToDeath() cleanly *after* binderDied() is delivered
to the given recipient; that requires that we have the hard reference
linkage described above.  The fix is to replace the hard global
reference with a weak reference to the DVM-side DeathRecipient
after we deliver binderDied() to that recipient.  In the case
where the caller has retained their own reference to the instance
(i.e. they might still call unlinkToDeath() on it later), the
weak reference stays live and everything works cleanly (and is
reaped explicitly by unlinkToDeath() as usual).  In the case where
the caller has *not* retained the instance to call unlinkToDeath()
themselves, demoting to a weak DeathRecipient reference allows
the DeathRecipient to be GC'd, which in turn frees the DVM-side
BinderProxy it's tied to, and so on around the chain to free
all of the associated allocations.

Fixes bug 5174537

Change-Id: Ia4ad76e667140cc2a1b74508bbba652ab31ab876
2011-08-18 17:06:31 -07:00
..