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
Loading
Please register or sign in to comment