ãã®èšäºã§ã¯ãAndroidåãã®éçºã«é¢ããHabréã«é¢ããäžé£ã®èšäºãéããŸãã
2012 Crittercismã¬ããŒãã«ãããšãOutOfMemoryErrorã¯ã¢ãã€ã«ã¢ããªã®ã¯ã©ãã·ã¥ã®2çªç®ã®äž»èŠãªåå ã§ãã
æ£çŽãªãšãããBadooã§ã¯ããã®ãšã©ãŒããã¹ãŠã®ã¯ã©ãã·ã¥ã®ãããã«ãããŸããïŒãŠãŒã¶ãŒã衚瀺ããåçã®éã§ã¯é©ãããšã§ã¯ãããŸããïŒã OutOfMemoryãšã®æŠãã¯éªšã®æããäœæ¥ã§ãã Allocation Trackerãéžæããã¢ããªã±ãŒã·ã§ã³ã®äœ¿çšãéå§ããŸããã äºçŽãããã¡ã¢ãªã®ããŒã¿ã芳å¯ããŠãã¡ã¢ãªã®å²ãåœãŠãçãããé床ã§å¢å ããæžå°ãå¿ããããã€ãã®ã·ããªãªãç¹å®ããŸããã ãããã®ã·ããªãªã®åŸãããã€ãã®ã¡ã¢ãªãã³ããæºåããŠãMATïŒ
http://www.eclipse.org/mat/ ïŒã§åæããŸããã
çµæã¯é¢çœããæ°é±é以å
ã«ã¯ã©ãã·ã¥ã®æ°ãæžããããšãã§ããŸããã ã³ãŒãã«åºæã®ãã®ããããŸããããã»ãšãã©ã®Androidã¢ããªã±ãŒã·ã§ã³ã«ç¹æã®å
žåçãªåé¡ãæããã«ããŸããã
ä»æ¥ã¯ãã¡ã¢ãªãªãŒã¯ã®ç¹å®ã®ã±ãŒã¹ã«ã€ããŠèª¬æããŸãã å€ãã®äººã圌ã«ã€ããŠç¥ã£ãŠããŸããããã°ãã°ããã«ç®ãã€ã¶ã£ãŠããŸãïŒãããç¡é§ã§ãïŒã
android.os.Handlerã®èª€çšã«é¢é£ããã¡ã¢ãªãªãŒã¯ã«ã€ããŠèª¬æããŸãã å®å
šã«æããã§ã¯ãããŸãããããã³ãã©ãŒã«å
¥ãããã®ã¯ãã¹ãŠã¡ã¢ãªãŒå
ã«ãããã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠãã°ããã¯ãªã¢ã§ããŸããã æã«ã¯éåžžã«é·ãã
å°ãåŸã«ãäœãèµ·ãã£ãŠããã®ãããªãã¡ã¢ãªã解æŸã§ããªãã®ããäŸã§ç€ºããŸãã 奜å¥å¿ã¯ãªãããåé¡ã®å¯ŸåŠæ¹æ³ãç¥ãããå Žåã¯ãèšäºã®æåŸã«ããçµè«ã«é²ãã§ãã ããã ãŸãã¯ãããã«ãªãŒãã³ã¢ã¯ã»ã¹ã«ããå°ããªã©ã€ãã©ãªã®ããŒãž
https://github.com/badoo/android-weak-handlerã«ç§»åããŸã ã
ããã§ãããã«ãæµãããããšã¯äœã§ããïŒ ãããç解ããŸãããã
ç°¡åãªäŸ
ããã¯éåžžã«åçŽãªActivityã¯ã©ã¹ã§ãã 800ç§åŸã«ããã¹ããå€æŽããå¿
èŠããããšããŸãã ãã¡ããããã®äŸã¯ã°ãããŠããŸãããèšæ¶ã®æµããã©ã®ããã«æµãããããã瀺ããŠããŸãã
ãã³ãã©ãŒã«æçš¿ããå¿åã®Runnableã«æ³šæããŠãã ããã é·ãã¿ã€ã ã¢ãŠãã«æ³šæããããšãéèŠã§ãã
ãã¹ãã®ããã«ããã®äŸãå®è¡ããé»è©±ã7åå転ãããŠãç»é¢ã®åããå€æŽããã¢ã¯ãã£ããã£ãåäœæããŸããã 次ã«ãã¡ã¢ãªãã³ããååŸããMATïŒ
http://www.eclipse.org/mat/ ïŒã§éããŸããã
OQLã䜿çšããŠãActivityã¯ã©ã¹ã®ãã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã衚瀺ããç°¡åãªã¯ãšãªãå®è¡ããŸãã
select * from instanceof android.app.Activity
OQLã«ã€ããŠèªãããšã匷ããå§ãããŸããããã¯ãã¡ã¢ãªåæã«éåžžã«åœ¹ç«ã¡ãŸãã
ããã§
visualvm.java.net/oqlhelp.htmlãŸãã¯ããã§
help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Freference%2Foqlsyntax.htmlã èªãããšãã§ã
ãŸã ã
ã¡ã¢ãªã«ã¯7ã€ã®ã¢ã¯ãã£ããã£ã€ã³ã¹ã¿ã³ã¹ããããŸãã ããã¯å¿
èŠãª7åã§ãã ã¬ããŒãžã³ã¬ã¯ã¿ãŒãã¡ã¢ãªãã䜿çšæžã¿ãªããžã§ã¯ããåé€ã§ããªãã£ãçç±ãèŠãŠã¿ãŸãããã ã¢ã¯ãã£ããã£ã®1ã€ãžã®ãªã³ã¯ã®æçã°ã©ããéããŸãããã
ã¹ã¯ãªãŒã³ã·ã§ããã¯ã
ãã®$ 0ãã¢ã¯ãã£ããã£ãæããŠããããšã瀺ããŠããŸãã ããã¯ãå¿åã¯ã©ã¹ããå€éšã¯ã©ã¹ãžã®æé»çãªåç
§ã§ãã Javaã§ã¯ãå€éšãã£ãŒã«ããã¡ãœããã«ã¢ã¯ã»ã¹ããªãå Žåã§ããå¿åã¯ã©ã¹ã«ã¯åžžã«å€éšã¯ã©ã¹ãžã®æé»çãªåç
§ããããŸãã Javaã¯å®ç§ã§ã¯ãªãã人çã¯èŠçã§ãã ãã®ãããªããšãåç«ã
次ã«ã
ãã®$ 0ãžã®åç
§ã¯ããªã³ã¯ãããã¡ãã»ãŒãžãªã¹ãã«ä¿åããã
ã³ãŒã«ããã¯ã«ä¿åãããŸãã ãã§ãŒã³ã®æåŸã«ã¯ãã¡ã€ã³ã¹ã¬ããã®ã¹ã¿ãã¯å
ã®ããŒã«ã«ãªã³ã¯ããããŸãã æããã«ãããã¯UIã¹ã¬ããã®ã¡ã€ã³ã«ãŒãå
ã®ããŒã«ã«å€æ°ã§ããããµã€ã¯ã«ãå®äºãããšè§£æŸãããŸãã ç§ãã¡ã®å Žåãããã¯ã¢ããªã±ãŒã·ã§ã³ãäœæ¥ãå®äºããåŸã«çºçããŸãã
ãã®ãããRunnableãŸãã¯Messageããã³ãã©ãŒã«é
眮ãããšãã¡ãã»ãŒãžãæ©èœãããŸã§LooperThreadã®ã¡ãã»ãŒãžãªã¹ãã«ä¿åãããŸãã ä¿çäžã®ã¡ãã»ãŒãžãé
眮ãããšããã®ã¡ãã»ãŒãžãæ¥ããŸã§ã¡ã¢ãªã«æ®ãããšã¯æããã§ãã ã¡ã¢ãªå
ã®ã¡ãã»ãŒãžãšãšãã«ãã¡ãã»ãŒãžãåç
§ãããã¹ãŠã®ãªããžã§ã¯ããæ瀺çããã³æé»çã«ååšããŸãã
ãããŠãããªãã¯ããã«ã€ããŠäœããããå¿
èŠããããŸãã
éçã¯ã©ã¹ãœãªã¥ãŒã·ã§ã³
ãã®$ 0ãªã³ã¯ãåé€ããŠãåé¡ã解決ããŠã¿ãŸãããã ãããè¡ãã«ã¯ãå¿åã¯ã©ã¹ãéçã¯ã©ã¹ã«å€æããŸãã
èµ·åããé»è©±ãæ°ååããŠãã¡ã¢ãªãã³ããåéããŸãã
åã³è€æ°ã®ã¢ã¯ãã£ããã£ïŒ ã¬ããŒãžã³ã¬ã¯ã¿ãŒãããããåé€ã§ããªãã£ãçç±ãèŠãŠã¿ãŸãããã
ãªã³ã¯ã°ã©ãã®äžéšã«æ³šæããŠãã ãããã¢ã¯ãã£ããã£ã¯ãDoneRunnableã¯ã©ã¹å
ã®mTextViewããmContextãªã³ã¯ã«æ ŒçŽãããŸãã æããã«ãéçã¯ã©ã¹ãåç¬ã§äœ¿çšããã ãã§ã¯ãã¡ã¢ãªãªãŒã¯ãåé¿ããã«ã¯äžååã§ãã ä»ã®ããšãããå¿
èŠããããŸãã
éçã¯ã©ã¹ãšWeakReferenceã䜿çšãããœãªã¥ãŒã·ã§ã³
ã¡ã¢ãªãã³ãã®èª¿æ»äžã«èŠã€ãã£ãTextViewãªã³ã¯ãåãé€ãã·ãŒã±ã³ã·ã£ã«ãªæ¹æ³ãç¶ç¶ããŸãã
WeakReferenceã«ã¯TextViewãžã®ãªã³ã¯ãä¿æãããŠããããšã«æ³šæããŠãã ããã WeakReferenceã®äœ¿çšã«ã¯ç¹å¥ãªæ³šæãå¿
èŠã§ãããã®ãããªãªã³ã¯ã¯ãã€ã§ããªã»ããã§ããŸãã ãããã£ãŠãæåã«ããŒã«ã«å€æ°ãžã®ãªã³ã¯ãä¿åããåŸè
ã ãã䜿çšããŠãnullããã§ãã¯ããŸãã
ã¡ã¢ãªãã³ããå®è¡ãå転ãããã³åéããŸãã
ç®çãéæããŸããïŒ 1ã€ã®ã¢ã¯ãã£ããã£ã®ã¿ã念é ã«çœ®ããŠããŸãã åé¡ã¯è§£æ±ºããŸããã
ãã®ã¢ãããŒãã䜿çšããã«ã¯ã次ã®ãã®ãå¿
èŠã§ãã
- éçãªå
éšãŸãã¯å€éšã¯ã©ã¹ã䜿çšãã
- åç
§ãããã¹ãŠã®ãªããžã§ã¯ãã«WeakReferenceã䜿çšããŸãã
ãã®æ¹æ³ã¯è¯ãã§ããïŒ
å
ã®ã³ãŒããšãå®å
šãªãã³ãŒããæ¯èŒãããšã倧éã®ããã€ãºããé¡èã§ãã ã³ãŒããç解ããã®ã劚ãããã®ãµããŒããè€éã«ããŸãã ãã®ãããªã³ãŒããæžãããšã¯ãããªããäœããå¿ãããåŸç¹ãããããããšãã§ãããšããäºå®ã¯èšããŸã§ããªãããŸã åã³ã§ãã
ããè¯ã解決çãããã®ã¯è¯ãããšã§ãã
onDestroyã®ãã¹ãŠã®ã¡ãã»ãŒãžãã¯ãªã¢ããŸã
Handlerã¯ã©ã¹ã«ã¯ãèå³æ·±ãéåžžã«äŸ¿å©ãªã¡ãœãã
removeCallbacksAndMessagesããããåŒæ°ãšããŠnullãåããŸãã ãã®ãã³ãã©ã®ãã¥ãŒå
ã®ãã¹ãŠã®ã¡ãã»ãŒãžãåé€ããŸãã
onDestroyã§äœ¿çšããŠã¿ãŸããã
ãã¡ã¢ãªãã³ããå®è¡ãå転ãåé€ããŸãã
ãããïŒ 1ã€ã®ã¢ã¯ãã£ããã£ã¯ã©ã¹ã®ã¿ã
ãã®æ¹æ³ã¯ãåã®æ¹æ³ãããã¯ããã«åªããŠããŸããä»éããã³ãŒãã®éã¯æå°éã§ããããã¹ãç¯ããªã¹ã¯ã¯ã¯ããã«äœããªããŸãã 1ã€ã®äžå¹žã¯ã
onDestroyã¡ãœãããŸãã¯ã¡ã¢ãªãã¯ãªãŒã³ã¢ããããå¿
èŠãããå Žæã§ã¯ãªãŒã³ã¢ãããåŒã³åºãããšãå¿ããªãããšã§ãã
åšåº«ã«ãã1ã€ã®æ¹æ³ããããŸãã
WeakHandlerã䜿çšãããœãªã¥ãŒã·ã§ã³
BadooããŒã ã¯Handler-
WeakHandlerãäœæããŸãã ã ããã¯ããã³ãã©ãŒãšãŸã£ããåãããã«åäœããã¯ã©ã¹ã§ãããã¡ã¢ãªãªãŒã¯ãæé€ããŸãã
ã¡ã¢ãªãªãŒã¯ãåé¿ããããã«ãœãããªã³ã¯ãšããŒããªã³ã¯ã䜿çšããŸãã åäœã®åçã«ã€ããŠã¯å°ãåŸã§èª¬æããŸãããããã§ã¯ã³ãŒããèŠãŠã¿ãŸãããã
å
ã®ã³ãŒãã«éåžžã«äŒŒãŠããŸãããïŒ 1ã€ã®å°ããªè©³çŽ°ã ãïŒ
android.os.Handlerã䜿çšãã代ããã«ã
WeakHandlerã䜿çšã
ãŸãã ã å§ããŸããããé»è©±ãæ°åå転ãããŠãã¡ã¢ãªãã³ããåé€ããŸãã
ã€ãã«ïŒ ã³ãŒãã¯æ¶ã®ããã«ãããã§ãã¡ã¢ãªã¯æµããŸããã
ãã®æ¹æ³ãæ°ã«å
¥ã£ãå Žåãè¯ããã¥ãŒã¹ããããŸã
ãWeakHandlerã®äœ¿çš
ã¯éåžžã«ç°¡åã§ãã
ãããžã§ã¯ãã«MavenäŸåé¢ä¿ãè¿œå ããŸãã
repositories { maven { repositories { url 'https://oss.sonatype.org/content/repositories/releases/' } } } dependencies { compile 'com.badoo.mobile:android-weak-handler:1.0' }
ã³ãŒãã«
WeakHandlerãã€ã³ããŒãããŸãã
import com.badoo.mobile.util.WeakHandler
ãœãŒã¹ã³ãŒãã¯githubïŒ
github.com/badoo/android-weak-handlerã«æçš¿ãããŠããŸãã
WeakHandlerã®ä»çµã¿
äž»ãªã¢ã€ãã¢ã¯ã
WeakHandlerãžã®ããŒããªã³ã¯ãããéããã¡ãã»ãŒãžãŸãã¯Runnableãžã®ããŒããªã³ã¯ãä¿æããããš
ã§ã ã
WeakHandlerãã¡ã¢ãªããåé€ã§ããããã«ãªããšããã«ãä»ã®ãã¹ãŠã®ãã®ãåé€ããå¿
èŠããããŸãã
説æãç°¡åã«ããããã«ãå¿åRunnableãåçŽãªHandlerãš
WeakHandlerã«é
眮ããããšã®éãã瀺ãç°¡åãªå³ã瀺ã
ãŸã ã
äžã®å³ã«æ³šç®ããŠãã ãããã¢ã¯ãã£ããã£ã¯Runnableããã¹ããããã³ãã©ãŒãåç
§ããŸãïŒã¹ã¬ãããåç
§ããã¡ãã»ãŒãžãã¥ãŒã«é
眮ããŸãïŒã RunnableããActivityãžã®æé»çãªããã¯ãªã³ã¯ãé€ãããã¹ãŠåé¡ãããŸããã Messageãåç¶ãããã¥ãŒã«ããéããThreadãåç¶ããŠããéã¯ãã°ã©ãå
šäœãã¬ããŒãžã³ã¬ã¯ã¿ãŒã§åéããããšã¯ã§ããŸããã åãã¢ã¯ãã£ããã£ãå«ãã
äžã®å³ã§ã¯ãã¢ã¯ãã£ããã£ã¯å
éšã«ãã³ãã©ãä¿æããWeakHandlerãåç
§ããŠããŸãã Runnableãé
眮ããããã«äŸé Œãããšã圌ã¯ãããWeakRunnableã«ã©ããããŠãã¥ãŒã«æçš¿ããŸãã ãããã£ãŠãã¡ãã»ãŒãžãã¥ãŒã¯WeakRunnableã®ã¿ãåç
§ããŸãã WeakRunnableã«ã¯ãå
ã®Runnableãžã®WeakReferenceãå«ãŸããŠããŸãã ã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ãã€ã§ãã¯ãªãŒãã³ã°ã§ããŸãã 圌ãäºåã«ã¯ãªã¢ããªãããã«ãWeakHandlerã¯Runnableãžã®ããŒããªã³ã¯ãä¿æããŸãã ãã ããWeakHandlerèªäœãåé€ã§ããããã«ãªããšããã«ãRunnableãåé€ã§ããŸãã
WeakHandlerã¯å€éšããåç
§ãããå¿
èŠãããããšãå¿ããªãããã«æ³šæããå¿
èŠããããŸããããããªããšãã¬ããŒãžã³ã¬ã¯ã¿ãŒã«ãã£ãŠãã¹ãŠã®ã¡ãã»ãŒãžãã¯ãªã¢ãããŸãã
çµè«
Androidã§
postDelayedã䜿çšããã®ã¯
èŠãç®ã»ã©ç°¡åã§ã¯ãããŸãããã¡ã¢ãªãæµããªãããã«è¿œå ã®æé ãå®è¡ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ã次ã®æ¹æ³ã䜿çšã§ããŸãã
- éçãªå
éšã¯ã©ã¹Runnable / Handlerãå€éšã¯ã©ã¹ãžã®WeakReferencesãšãšãã«äœ¿çšããŸãã
- onDestroyã¡ãœããããHandlerã¯ã©ã¹ã®ãã¹ãŠã®ã¡ãã»ãŒãžãã¯ãªã¢ããŸãã
- Badooã®WeakHandlerã䜿çšããŸãïŒ https://github.com/badoo/android-weak-handler ïŒã
éžæã¯ããªã次第ã§ãã æåã®æ¹æ³ã¯ééããªãæ ãè
åãã§ã¯ãããŸããã 2çªç®ã®æ¹æ³ã¯éåžžã«åçŽã«èŠããŸãããè¿œå ã®äœæ¥ãå¿
èŠã§ãã 3çªç®ã¯ç§ãã¡ã®ãæ°ã«å
¥ãã§ããã泚æããå¿
èŠããããŸããå¿
èŠã«ãªããŸã§ã
WeakHandlerã«ã¯å€éšãªã³ã¯ãå¿
èŠã§ããããããªããšãã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ãã¥ãŒããã®ãã¹ãŠã®ã¡ãã»ãŒãžãšãšãã«ãããåé€ããŸãã
ããªãã«å¹žéãïŒ ç§ãã¡ãšäžç·ã«-ãã®ãããã¯ã¯ç¶ç¶ãããŸãã
è±èªã®ããã°ã®èšäºïŒ
bit.ly/AndroidHandlerMemoryLeaksDmitry Voronkevichã䞻任éçºè