톰캣 메모리릭 문제에 대해서 많이 좋아질 것으로 예상됩니다.
스프링소스의 개발자이며, 톰캣 Commitor인 Mark Thomas(subversion id : markt)에 의해 Memory Leak protection 기능이 새로 생기게 되었습니다. 원래는 톰캣 7부터 적용하려고 했는데, 톰캣 6.0.24 부터 적용되었다고 합니다. 6.0.25버전에는 Memory leak 체크 api도 지원하는 군요~ 덜덜
다음의 내용으로 Change log 6.0.25에 있습니다. ..
“Add new "Find leaks" command to the Manager application” |
Mark는 이 OOME가 발생하는 원인을 톰캣이 아닌 Jvm, library라고 언급하였고, 그 예를 적었습니다.
(1) Application, Library code 에 의해서 발생
A. JDBC driver
B. Logging framework
C. ThreadLocal의 object를 저장하고 remove하지 않아서
D. 쓰레드를 시작시키고 멈추지 않아서
(2) Java Api에 의해서도 발생
A. Using the javax.imageio API (the Google Web Toolkit can trigger this)
B. Using java.beans.Introspector.flushCaches() (Tomcat does this to prevent memory leaks caused by this caching)
C. Using XML parsing (the root cause is unknown due to a bug in the JRE)
D. Using RMI (somewhat ironically, causes a leak related to the garbage collector)
E. Reading resources from JAR files
이런 문제가 나타나는 것의 이유 중의 하나는 Java의 Class Loader에서는 아직 object에 대해서 de-register 기능이 없습니다. 그래서 톰캣 web class loader는 이런 부분을 지원했습니다.
Mark는 이런 OOME 문제 해결을 위해서 다음을 하였습니다.
Org.apache.ctalina.loader.WebappClassLoader (http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/loader/WebappClassLoader.java?view=markup )클래스에 clearRefereneces() 메소드를 추가하여 톰캣에 의해서 load된 object들을 de-register하여 gc가 되도록 하였습니다. PermGen을 싹 지우고 시작하는 것 같습니다.
또한 org.apache.catalina.core.JreMemoryLeakPreventionListener 클래스
(http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?view=markup ) 를 추가하여 원인파악을 쉽게 할 수 있도록 api를 제공하였습니다.
Mark는 java.util.logging 처럼 JRE에서 로딩되는 경우에 대해서는 Tomcat단에서 처리할 수 없으니, 다른 LogManager를 쓰라고 권고하고 있습니다.
Static ThreadLocal의 경우도 해결이 힘들었는데. Tomcat 6.0.24는 아래와 같이 detect를 하고 webclassloader에서 ThreadLocalMap을 inspect함으로서 잘 테스트했다고 적혀 있네요.
Mar 17, 2010 10:23:13 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap
SEVERE: A web application created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@44676e3f]) and a value of type [test.leak.threadlocal.value.MyCounter] (value [test.leak.threadlocal.value.MyCounter@62770d2e]) but failed to remove it when the web application was stopped. To prevent a memory leak, the ThreadLocal has been forcibly removed.
Tomcat manager의 "Find leaks" 을 누르면 아래와 같이 알려줄 수는 있으나, 상세한 것은 Eclipse MAT (http://www.eclipse.org/mat/)을 쓰라고 합니다.
The following web applications were stopped (reloaded, undeployed), but their
classes from previous runs are still loaded in memory, thus causing a memory
leak (use a profiler to confirm):
/testWeb
l 참고자료
http://java.dzone.com/articles/memory-leak-protection-tomcat
http://java.dzone.com/articles/mark-thomas-apache-tomcat-7
http://tomcat.apache.org/tomcat-6.0-doc/changelog.html
http://wiki.apache.org/tomcat/MemoryLeakProtection?action=diff&rev1=3&rev2=4
'java core' 카테고리의 다른 글
Desktop JVM 보안 문제 (0) | 2010.04.17 |
---|---|
문제 해결 가이드 링크 (0) | 2010.04.15 |
-XX:+AggressiveOpts -XX:+DoEscapeAnalysis 테스트 (0) | 2010.03.02 |
JVM crash.. (0) | 2010.02.25 |
Exception 이름과 실제 내용만 찍기 (0) | 2010.02.25 |