/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 5 ĠSquare , ĠInc . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġleak can ary Ċ Ċ import Ġsh ark . Sh ark Log Ċ import Ġjava . lang . ref . Reference Queue Ċ import Ġjava . util . UUID Ċ import Ġjava . util . concurrent . Executor Ċ Ċ /** Ċ Ġ* Ġ[ Object Watcher ] Ġcan Ġbe Ġpassed Ġobjects Ġto Ġ[ watch ]. ĠIt Ġwill Ġcreate Ġ[ Key ed Weak Reference ] Ġinstances Ċ Ġ* Ġthat Ġreference Ġw atches Ġobjects , Ġand Ġcheck Ġif Ġthose Ġreferences Ġhave Ġbeen Ġcleared Ġas Ġexpected Ġon Ċ Ġ* Ġthe Ġ[ check Ret ained Executor ] Ġexecutor . ĠIf Ġnot , Ġthese Ġobjects Ġare Ġconsidered Ġretained Ġand Ċ Ġ* Ġ[ Object Watcher ] Ġwill Ġthen Ġnotify Ġregistered Ġ[ On Object Ret ained Listener ] s Ġon Ġthat Ġexecutor Ġthread . Ċ Ġ* Ċ Ġ* Ġ[ check Ret ained Executor ] Ġis Ġexpected Ġto Ġrun Ġits Ġtasks Ġon Ġa Ġbackground Ġthread , Ġwith Ġa Ġsignificant Ċ Ġ* Ġdelay Ġto Ġgive Ġthe ĠGC Ġthe Ġopportunity Ġto Ġidentify Ġweak ly Ġreachable Ġobjects . Ċ Ġ* Ċ Ġ* Ġ[ Object Watcher ] Ġis Ġthread Ġsafe . Ċ Ġ*/ Ċ // ĠThread Ġsafe Ġby Ġlocking Ġon Ġall Ġmethods , Ġwhich Ġis Ġreason ably Ġefficient Ġgiven Ġhow Ġoften Ċ // Ġthese Ġmethods Ġare Ġaccessed . Ċ class ĠObject Watcher Ġconstructor ( ĊĠ Ġprivate Ġval Ġclock : ĠClock , ĊĠ Ġprivate Ġval Ġcheck Ret ained Executor : ĠExecutor , ĊĠ Ġ/** ĊĠĠ Ġ* ĠCalls Ġto Ġ[ watch ] Ġwill Ġbe Ġignored Ġwhen Ġ[ isEnabled ] Ġreturns Ġfalse ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġval Ġis Enabled : Ġ() Ġ-> ĠBoolean Ġ= Ġ{ Ġtrue Ġ} Ċ ) Ġ: ĠRe ach ability Watcher Ġ{ ĊĊĠ Ġprivate Ġval Ġon Object Ret ained Listeners Ġ= Ġmutable Set Of < On Object Ret ained Listener >() ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReferences Ġpassed Ġto Ġ[ watch ]. ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġval Ġw atched Objects Ġ= Ġmutable Map Of < String , ĠKey ed Weak Reference >() ĊĊĠ Ġprivate Ġval Ġqueue Ġ= ĠReference Queue < Any >() ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReturns Ġtrue Ġif Ġthere Ġare Ġw atched Ġobjects Ġthat Ġaren 't Ġweak ly Ġreachable , Ġand ĊĠĠ Ġ* Ġhave Ġbeen Ġw atched Ġfor Ġlong Ġenough Ġto Ġbe Ġconsidered Ġretained . ĊĠĠ Ġ*/ ĊĠ Ġval Ġhas Ret ained Objects : ĠBoolean ĊĠĠĠ Ġ@ Synchron ized Ġget () Ġ{ ĊĠĠĠĠĠ Ġremove Weak ly Reach able Objects () ĊĠĠĠĠĠ Ġreturn Ġw atched Objects . any Ġ{ Ġit . value . ret ained U ptime Millis Ġ!= Ġ- 1 L Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReturns Ġthe Ġnumber Ġof Ġretained Ġobjects , Ġie Ġthe Ġnumber Ġof Ġw atched Ġobjects Ġthat Ġaren 't Ġweak ly ĊĠĠ Ġ* Ġreachable , Ġand Ġhave Ġbeen Ġw atched Ġfor Ġlong Ġenough Ġto Ġbe Ġconsidered Ġretained . ĊĠĠ Ġ*/ ĊĠ Ġval Ġretained Object Count : ĠInt ĊĠĠĠ Ġ@ Synchron ized Ġget () Ġ{ ĊĠĠĠĠĠ Ġremove Weak ly Reach able Objects () ĊĠĠĠĠĠ Ġreturn Ġw atched Objects . count Ġ{ Ġit . value . ret ained U ptime Millis Ġ!= Ġ- 1 L Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReturns Ġtrue Ġif Ġthere Ġare Ġw atched Ġobjects Ġthat Ġaren 't Ġweak ly Ġreachable , Ġeven ĊĠĠ Ġ* Ġif Ġthey Ġhaven 't Ġbeen Ġw atched Ġfor Ġlong Ġenough Ġto Ġbe Ġconsidered Ġretained . ĊĠĠ Ġ*/ ĊĠ Ġval Ġhas W atched Objects : ĠBoolean ĊĠĠĠ Ġ@ Synchron ized Ġget () Ġ{ ĊĠĠĠĠĠ Ġremove Weak ly Reach able Objects () ĊĠĠĠĠĠ Ġreturn Ġw atched Objects . isNotEmpty () ĊĠĠĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠReturns Ġthe Ġobjects Ġthat Ġare Ġcurrently Ġconsidered Ġretained . ĠUseful Ġfor Ġlogging Ġpurposes . ĊĠĠ Ġ* ĠBe Ġcareful Ġwith Ġthose Ġobjects Ġand Ġrelease Ġthem ĠAS AP Ġas Ġyou Ġmay Ġcreating Ġlonger Ġli ved Ġle aks ĊĠĠ Ġ* Ġthen Ġthe Ġone Ġthat Ġare Ġalready Ġthere . ĊĠĠ Ġ*/ ĊĠ Ġval Ġretained Objects : ĠList < Any > ĊĠĠĠ Ġ@ Synchron ized Ġget () Ġ{ ĊĠĠĠĠĠ Ġremove Weak ly Reach able Objects () ĊĠĠĠĠĠ Ġval Ġinstances Ġ= Ġmutable ListOf < Any >() ĊĠĠĠĠĠ Ġfor Ġ( weak Reference Ġin Ġw atched Objects . values ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( weak Reference . ret ained U ptime Millis Ġ!= Ġ- 1 L ) Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġval Ġinstance Ġ= Ġweak Reference . get () ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( instance Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinstances . add ( instance ) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġreturn Ġinstances ĊĠĠĠ Ġ} ĊĊĠ Ġ@ Synchron ized Ġfun Ġadd On Object Ret ained Listener ( listener : ĠOn Object Ret ained Listener ) Ġ{ ĊĠĠĠ Ġon Object Ret ained Listeners . add ( listener ) ĊĠ Ġ} ĊĊĠ Ġ@ Synchron ized Ġfun Ġremove On Object Ret ained Listener ( listener : ĠOn Object Ret ained Listener ) Ġ{ ĊĠĠĠ Ġon Object Ret ained Listeners . remove ( listener ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠIdent ical Ġto Ġ[ watch ] Ġwith Ġan Ġempty Ġstring Ġreference Ġname . ĊĠĠ Ġ*/ ĊĠ Ġ@ Deprecated ( ĊĠĠĠ Ġ" Add Ġdescription Ġparameter Ġexplaining Ġwhy Ġan Ġobject Ġis Ġw atched Ġto Ġhelp Ġunderstand Ġleak Ġtraces .", ĊĠĠĠ Ġreplace With Ġ= ĠReplace With ( ĊĠĠĠĠĠ Ġ" expect Weak ly Reach able ( w atched Object , Ġ\" Explain Ġwhy Ġthis Ġobject Ġshould Ġbe Ġgarbage Ġcollected Ġsoon \") " ĊĠĠĠ Ġ) ĊĠ Ġ) ĊĠ Ġfun Ġwatch ( w atched Object : ĠAny ) Ġ{ ĊĠĠĠ Ġexpect Weak ly Reach able ( w atched Object , Ġ"") ĊĠ Ġ} ĊĊĠ Ġ@ Deprecated ( ĊĠĠĠ Ġ" Method Ġrenamed Ġexpect Weak ly Reach able () Ġto Ġclarify Ġusage .", ĊĠĠĠ Ġreplace With Ġ= ĠReplace With ( ĊĠĠĠĠĠ Ġ" expect Weak ly Reach able ( w atched Object , Ġdescription )" ĊĠĠĠ Ġ) ĊĠ Ġ) ĊĠ Ġfun Ġwatch ( ĊĠĠĠ Ġw atched Object : ĠAny , ĊĠĠĠ Ġdescription : ĠString ĊĠ Ġ) Ġ{ ĊĠĠĠ Ġexpect Weak ly Reach able ( w atched Object , Ġdescription ) ĊĠ Ġ} ĊĊĊĠ Ġ@ Synchron ized Ġoverride Ġfun Ġexpect Weak ly Reach able ( ĊĠĠĠ Ġw atched Object : ĠAny , ĊĠĠĠ Ġdescription : ĠString ĊĠ Ġ) Ġ{ ĊĠĠĠ Ġif Ġ(! isEnabled ()) Ġ{ ĊĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĠĠĠ Ġremove Weak ly Reach able Objects () ĊĠĠĠ Ġval Ġkey Ġ= ĠUUID . randomUUID () ĊĠĠĠĠĠ Ġ. toString () ĊĠĠĠ Ġval Ġwatch U ptime Millis Ġ= Ġclock . uptime Millis () ĊĠĠĠ Ġval Ġreference Ġ= ĊĠĠĠĠĠ ĠKey ed Weak Reference ( w atched Object , Ġkey , Ġdescription , Ġwatch U ptime Millis , Ġqueue ) ĊĠĠĠ ĠSh ark Log . d Ġ{ ĊĠĠĠĠĠ Ġ" Watch ing Ġ" Ġ+ ĊĠĠĠĠĠĠĠ Ġ( if Ġ( w atched Object Ġis ĠClass <* >) Ġw atched Object . toString () Ġelse Ġ" instance Ġof Ġ${ w atched Object . java Class . name }") Ġ+ ĊĠĠĠĠĠĠĠ Ġ( if Ġ( description . isNotEmpty ()) Ġ" Ġ($ description )" Ġelse Ġ"") Ġ+ ĊĠĠĠĠĠĠĠ Ġ" Ġwith Ġkey Ġ$ key " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġw atched Objects [ key ] Ġ= Ġreference ĊĠĠĠ Ġcheck Ret ained Executor . execute Ġ{ ĊĠĠĠĠĠ Ġmove To Ret ained ( key ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠClear s Ġall Ġ[ Key ed Weak Reference ] Ġthat Ġwere Ġcreated Ġbefore Ġ[ heap Dump U ptime Millis ] Ġ( based Ġon ĊĠĠ Ġ* Ġ[ clock ] Ġ[ Clock . uptime Millis ]) ĊĠĠ Ġ*/ ĊĠ Ġ@ Synchron ized Ġfun Ġclear Objects W atched Before ( heap Dump U ptime Millis : ĠLong ) Ġ{ ĊĠĠĠ Ġval Ġweak Ref sTo Remove Ġ= ĊĠĠĠĠĠ Ġw atched Objects . filter Ġ{ Ġit . value . watch U ptime Millis Ġ<= Ġheap Dump U ptime Millis Ġ} ĊĠĠĠ Ġweak Ref sTo Remove . values . forEach Ġ{ Ġit . clear () Ġ} ĊĠĠĠ Ġw atched Objects . keys . removeAll ( weak Ref sTo Remove . keys ) ĊĠ Ġ} ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠClear s Ġall Ġ[ Key ed Weak Reference ] ĊĠĠ Ġ*/ ĊĠ Ġ@ Synchron ized Ġfun Ġclear W atched Objects () Ġ{ ĊĠĠĠ Ġw atched Objects . values . forEach Ġ{ Ġit . clear () Ġ} ĊĠĠĠ Ġw atched Objects . clear () ĊĠ Ġ} ĊĊĠ Ġ@ Synchron ized Ġprivate Ġfun Ġmove To Ret ained ( key : ĠString ) Ġ{ ĊĠĠĠ Ġremove Weak ly Reach able Objects () ĊĠĠĠ Ġval Ġretained Ref Ġ= Ġw atched Objects [ key ] ĊĠĠĠ Ġif Ġ( ret ained Ref Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠ Ġretained Ref . ret ained U ptime Millis Ġ= Ġclock . uptime Millis () ĊĠĠĠĠĠ Ġon Object Ret ained Listeners . forEach Ġ{ Ġit . on Object Ret ained () Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġremove Weak ly Reach able Objects () Ġ{ ĊĠĠĠ Ġ// ĠWeak References Ġare Ġen queued Ġas Ġsoon Ġas Ġthe Ġobject Ġto Ġwhich Ġthey Ġpoint Ġto Ġbecomes Ġweak ly ĊĠĠĠ Ġ// Ġreachable . ĠThis Ġis Ġbefore Ġfinal ization Ġor Ġgarbage Ġcollection Ġhas Ġactually Ġhappened . ĊĠĠĠ Ġvar Ġref : ĠKey ed Weak Reference ? ĊĠĠĠ Ġdo Ġ{ ĊĠĠĠĠĠ Ġref Ġ= Ġqueue . poll () Ġas ĠKey ed Weak Reference ? ĊĠĠĠĠĠ Ġif Ġ( ref Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġw atched Objects . remove ( ref . key ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ġwhile Ġ( ref Ġ!= Ġnull ) ĊĠ Ġ} Ċ } Ċ