Javaã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã§ThreadLocalå©ç¨æã®æ³¨æç¹
æ¬æ¥ã¯Java EE Advent Calendarã¨JPOUG Advent Calndarã®14æ¥ç®ã§ã*1ã
ãã¦ãå
æ¥11/9ã®JJUG CCCã§è©±ãã¦ããå
容ã§ãJavaã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã§ã¯ãã¢ããªã±ã¼ã·ã§ã³ããThreadLocalã¯æ¥µåå©ç¨ããªãæ¹ãããã¨ã®ã¹ã©ã¤ããè¼ãã¦ãã¾ããã
ããããå½æ¥ã¯æéããªããã¾ãåèæ
å ±ç¨åº¦ã§ããã®ã§ã説æãçãã¦ãã¾ããã
ããã«ã¤ãã¦ããã®ã¨ã³ããªã§ã¯å°ãä¸å¯§ã«èª¬æããããã¨æãã¾ãã
å®ã¯ãä¸è¨ã¹ã©ã¤ãã¯ãå½æ¥è©±ããå 容ãã以ä¸ã®ä¿®æ£ãå ãã¦ãã¾ãã
- ã極åå©ç¨ããªããâã注æãã¦å©ç¨ãã«å¤æ´
- ãåå©ç¨åæã®ã¹ã¬ããã«ç´ã¥ããããã¢ããªã§æ示çã«ç ´æ£ãã追è¨
ããããµããªã«ã¯ãªãã®ã§ããã説æãã¦ããã¾ãããã
ThreadLocal
ã¾ããThreadLocalã«ã¤ãã¦é¦´æã¿ãèãæ¹ãããã¨æãã¾ãã®ã§ãç°¡åã«å¾©ç¿ãã¾ãããã
ThreadLocalã¯ãJavaã§ã¹ã¬ãããã¨ã«ãªãã¸ã§ã¯ããä¿æããããã®æ©æ§ã§ãããã¹ã¬ããã»ã¼ãã«ãã¼ã¿ã®å©ç¨ãè¡ãã便å©ãªã¯ã©ã¹ã§ãã
ã¤ã¡ã¼ã¸çã«ã¯ãã«ã¬ã³ãã¹ã¬ããããã¼ã«å¤ã®åºãå
¥ããè¡ããMapã®ãããªãã®ã§ã*2ã
ãªã©ãåèã«ãªãã¾ãã
ã¢ããªã±ã¼ã·ã§ã³ã§ç´æ¥çã«å©ç¨ããªãã§ãããã¬ã¼ã ã¯ã¼ã¯ãã3rd Party製ã®ã©ã¤ãã©ãªãªã©ã§ä½¿ããã¦ããã±ã¼ã¹ãããã¾ãã
ä¾ãã°æåãªãã®ã³ã°ã©ã¤ãã©ãªã§ããLog4jãLogbackã§ã¯MDC(Mapped Diagnostic Context)ãå®è£
ããããã«ãThreadLocalãå©ç¨ããã¦ãã¾ãã
åå©ç¨åæã®ã¹ã¬ãã
Javaã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã§ã¯ãè¤æ°ã¦ã¼ã¶ã¼ããã®åæã¢ã¯ã»ã¹ãå¹ççã«æãããã«ããªã¯ã¨ã¹ããã¨ã«ã¹ã¬ããã®çæãç ´æ£ãè¡ãã®ã§ã¯ãªããã¹ã¬ãããã¼ã«ãä½æãã¦ãããåå©ç¨ããã®ãä¸è¬çã§ãã
å®è£
ã«ãããã¾ãããã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã¯ããããä¸ã¤ã®Javaããã»ã¹ã¨ãªããä¸ã¤ä»¥ä¸ã®ã¢ããªã±ã¼ã·ã§ã³(warãear)ããããã¤ããã¦åä½ãããã¨ãå¤ãã§ãã
ãã®ãããã¹ã¬ãããã¼ã«ãè¤æ°ã®ã¢ããªã±ã¼ã·ã§ã³ã§å
±ç¨ããããªã½ã¼ã¹ã¨ãªããã¢ããªã±ã¼ã·ã§ã³ãã¢ã³ãããã¤ãã¦ããã¹ã¬ãããã¼ã«ã¯ãã®ã¾ã¾æ®ãå®è£
ãå¤ãã¨æãã¾ãã
ãã¡ãããå®éã®éç¨ã§ã¯ãã¢ããªã±ã¼ã·ã§ã³éã®ç«¶åãé¿ããããç¬ç«æ§ãä¿ã¤ããã«ãã¢ããªã±ã¼ã·ã§ã³ãã¨ã«ãªã½ã¼ã¹ãç¨æããã±ã¼ã¹ãããã¨ã¯æãã¾ãããåºæ¬çã«ã¯ã¢ããªã±ã¼ã·ã§ã³ã¨ãã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã®ãªã½ã¼ã¹ã¯ãã§ããã ãçã«ä¿ã£ã¦ãããããªé
æ
®ãå¿
è¦ã¨ããã¾ãã
ããã¯ã¹ã¬ãããã¼ã«ã ãã§ã¯ãªããDBã¨ã®æ¥ç¶ãã¼ã«ãªã©ãåæ§ã§ãã
ä¸è¨ã®çµã¿åãã
ãã¦ããThreadLocalãã¨ãåå©ç¨åæã®ã¹ã¬ããããçµã¿åãããã¨ãã«ã©ããªããã
ä½ãèãã¦ããªãã¨ãã¢ããªã±ã¼ã·ã§ã³ãµã¼ãããã¢ããªã±ã¼ã·ã§ã³ãã¢ã³ãããã¤ããã¦ããã¹ã¬ããã¯æ®ã£ãã¾ã¾ã§ãããThreadLocalã¸ã®åç
§ã¯ç ´æ£ããã¾ããã
ãã®ãããåç
§ããã¦ãããªãã¸ã§ã¯ããã¯ã©ã¹ãGC対象ã¨ãªãããæ®ã£ã¦ãã¾ããã¨ã«ãªãã¾ãã®ã§ãã¡ã¢ãªãªã¼ã¯ãçºçãããè¦å ã¨ãªãã¾ãã
以ä¸ã®è³æP22-P42ã§åããããã説æããã¦ãã¾ãã®ã§ãå³ãªã©ãå«ãã¦åç
§ãã¦ã¿ã¦ãã ããã
ããã§ã¯ãWebLogic Serverã®æ¬çªåãããã¤ã¡ã³ããç¹°ãè¿ãè¡ããã¨ã«ãããçºçããOutOfMemoryErrorãJRockit Mission Controlã«å«ã¾ããMemory Leak Detector*3ãå©ç¨ãã¦ç¹å®ã»è§£æ±ºããä¾ã§ãããããã«éãããä»è£½åã§ã®é常ã®ã¢ã³ãããã¤ãä»ã®JVMã§ãçºçãããã®ã§ãã
解決ç
ThreadLocalã使ããªããã°åççã«çºçã¯ããªãã®ã§ãããå©ç¨ãããå ´åãå¤ã
çºçãã¾ããã3rd Partyã®ã©ã¤ãã©ãªã§æé»çã«å©ç¨ããã¦ããã±ã¼ã¹ãããã¾ãã
ããã¤ãæ¹æ³ãæ示ãã¾ãããå®éã«ã¯ããããã¤âã¢ããªã±ã¼ã·ã§ã³ã®å®è¡âã¢ã³ãããã¤ãç¹°ãè¿ããã¹ããã¦ãã¡ã¢ãªãªã¼ã¯ãçºçããªããã確èªãã ããã
ãªã¯ã¨ã¹ããã¨ã«ç¢ºå®ã«ThreadLocal#removeãã
ã¢ããªã±ã¼ã·ã§ã³ããç´æ¥ThreadLocalããã³ããªã³ã°ãã¦ããå ´åã¯ããããè¡ãã¹ãã§ãã
ãªã¯ã¨ã¹ãåä½ã«å¤ãåæåãã使ãæ¹ãããå ´åã¯ãfinallyãtry-with-resourcesã§ã©ããã¼ãã¦ããã®ä¸ã§ThreadLocalã®å¤ãç ´æ£ããããã«ãã¾ãããã
ããããªããã°ãåãããã¤ã«éãããä»ã®ãªã¯ã¨ã¹ãã§å©ç¨ããå¤ãè¦ãã¦ãã¾ããåé¡ãçºçãããã¨ãããã¾ãã
3rd Partyã©ã¤ãã©ãªãªã©ã§ç¨æããã¦ããç ´æ£ã¡ã½ãããå¼ã³åºã
- Log4Jã§ããã°ãLogManager.shutdownãå¼ã³åºã
- LogBackã§ããã°ãLoggerContext#stopãå¼ã³åºã
ãªã©ã®æ¹æ³ãããããã§ãããæ£ç¢ºã«ã¯ããããã®ã©ã¤ãã©ãªã®ããã¥ã¡ã³ããªã©ãåç
§ãã ããã
ServletContext#destroyã®ä¸ãªã©ã§è¡ãã¨ããã§ãããã
ãªãã¬ã¯ã·ã§ã³ãç¨ãã¦åé¤ãã
ServletContext#destroyã®ä¸ãªã©ã§ããªãã¬ã¯ã·ã§ã³ãç¨ãã¦ThreadLocalãç ´æ£ããæ¹æ³ãæãããã¾ãã
ã®ãããªå®è£
ãåèã«ãªãã®ã§ã¯ãªãã§ããããã
Tomcatの場合は自動削除に対応ãã¦ããããã§ã*4ã
ã¢ããªã±ã¼ã·ã§ã³ã®ãããã¤ãè¡ãéã¯ãã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã®åèµ·åãä½µãã¦å®æ½ãã
身ãèããªãããããã¾ãããããããè¡ãã«è¶ãããã¨ã¯ããã¾ããã
ThreadLocalã«éããããã以å¤ã®ã¡ã¢ãªãªã¼ã¯ã解æ¶ããããèµ·åæã®ã¿ã«çºçããåé¡ãæ¤åºããã®ã«ãæå¹ã§ãã
ã¾ããããããé©ç¨ããããæ§æãå¤æ´ããã¨ãã«ã¯ãã©ããã¦ãåèµ·åãå¿
é ã«ãªãã±ã¼ã¹ãããã¾ãã
ã¾ã¨ã
- ThreadLocalãå®æã«å©ç¨ãããã¨ã¯ã¡ã¢ãªãªã¼ã¯ã®åå ã«ãªãå¾ã¾ãã
- WebLogic Serverã®æ¬çªåãããã¤ã¡ã³ãæ©è½ãªã©ãå©ç¨ãã¦ç¡åæ¢éç¨ãå®ç¾ããå ´åãç¹°ãè¿ããã¹ããã¦ã¡ã¢ãªãªã¼ã¯ãçºçããªãã確èªãã¦ãã ããã
- ãããã¤æã«åèµ·åãè¡ãã®ã¯æå¹ã§ãããããå¯è½ãªããã«æ§æãéç¨ãèæ ®ãã¦ãã ããã
*1:ä»å¹´ã¯ã©ã¡ãã被ãã¦ãã¾ã£ããã許ããâ¦
*2:å®éã®å®è£ ã¨ãã¦ã¯æ£ç¢ºã§ã¯ãªããããã¾ã§ã¤ã¡ã¼ã¸ã§ã
*3:HotSpot 7u40ã¨ä½µãã¦ãªãªã¼ã¹ãããJava Mission Control 5.2ã§ã¯æ®å¿µãªããã¾ã 移æ¤ããã¦ãã¾ãã
*4:WebLogic Serverã¨ããåæ§ã®æ©è½ãããã¨ãããªãã¨æã£ãã