
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/AndroidHandlerMemoryLeaks
Dmitry Voronkevichã䞻任éçºè