Tomcat의 Out of memory Exception 문의 드립니다.

5,989 views
Skip to first unread message

선영욱

unread,
Feb 2, 2010, 1:22:52 AM2/2/10
to ks...@googlegroups.com
안녕하세요.
 
다름이 아니라 Spring 2.5 + iBatis + DWR + SiteMash 의 구성으로 만든 웹 어플리케이션이 하나 있습니다.
 
그런데 보안심사 과정에서 스트레스 테스트 처럼 Requst를 사이트 전반적으로 요청을 하는 과정에서 웹 어플리케이션에서 out of memory 오류가 발생하였습니다.
 
2010. 1. 29 오후 1:03:21 org.apache.tomcat.util.http.Parameters processParameters
경고: Parameters: Invalid chunk ignored.
2010. 1. 29 오후 1:03:28 org.apache.catalina.connector.CoyoteAdapter service
심각: An exception or error occurred in the container during the request processing
java.lang.OutOfMemoryError: Java heap space
 at java.io.BufferedReader.<init>(BufferedReader.java:80)
 at java.io.BufferedReader.<init>(BufferedReader.java:91)
 at java.io.LineNumberReader.<init>(LineNumberReader.java:52)
 at org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep(ThrowableInformation.java:78)
 at org.apache.log4j.spi.LoggingEvent.getThrowableStrRep(LoggingEvent.java:407)
 at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:305)
 at org.apache.log4j.RollingFileAppender.subAppend(RollingFileAppender.java:263)
 at org.apache.log4j.WriterAppender.append(WriterAppender.java:160)
 at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
 at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
 at org.apache.log4j.Category.callAppenders(Category.java:206)
 at org.apache.log4j.Category.forcedLog(Category.java:391)
 at org.apache.log4j.Category.log(Category.java:856)
 at org.apache.commons.logging.impl.Log4JLogger.error(Log4JLogger.java:257)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:253)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
 at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
 at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
 at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
 at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
 at java.lang.Thread.run(Thread.java:595)
 
그래서 tomcat에 CATALINA_OPTS= -XX:MaxPermSize=128m;-Xms256m;-Xmx1024m 옵션을 추가하였는데도 테스트 과정에서 동일한 오류가 발생하였습니다.
 
보안심사를 진행하신 분께서는 DB Close 및 개발 부분에서의 잘못을 말씀을 하셨는데요, DB Close 부분은 iBatis에서 처리할 부분이라서 특별하게 한 것은 없어서(오히려 처리 한 것이 없어서 문제일까요?) 원인 파악에 어려움이 있습니다.
 
웹에서 검색해보면 스프링이 리플렉션을 많이 하기 때문에 반드시 옵션을 지정해야 한다고(http://www.ologist.co.kr/866) 하지만 어느정도로 지정을 해야 스트레스 테스트에도 견딜지 모르겠습니다.
 
그리고 이 문제가 메모리 설정이 작게 되어 그런 단순한 문제인 것인지, 아니면 개발에 문제가 있는 것인지 파악하려면 어떻게 해야 할지 모르겠습니다.
 
혹시 Spring 환경으로 개발한 웹 어플리케이션에 대해 스트레스 테스트 등의 테스트를 진행하셨던 분들의 소중한 조언을 부탁드리겠습니다.
 
감사합니다.
 
 
 

선영욱

unread,
Feb 2, 2010, 1:35:51 AM2/2/10
to Korea Spring User Group
추가 오류 라인입니다.

2010. 2. 1 오후 4:43:28 org.apache.catalina.core.StandardHostValve
custom
심각: Exception Processing ErrorPage[errorCode=500, location=/error.htm]
org.springframework.web.util.NestedServletException: Handler
processing failed; nested exception is java.lang.OutOfMemoryError:
Java heap space
at org.springframework.web.servlet.DispatcherServlet.doDispatch
(DispatcherServlet.java:924)
at org.springframework.web.servlet.DispatcherServlet.doService
(DispatcherServlet.java:807)
at org.springframework.web.servlet.FrameworkServlet.processRequest
(FrameworkServlet.java:571)
at org.springframework.web.servlet.FrameworkServlet.doGet
(FrameworkServlet.java:501)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:627)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter
(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter
(ApplicationFilterChain.java:188)
at org.apache.catalina.core.ApplicationDispatcher.invoke
(ApplicationDispatcher.java:679)
at org.apache.catalina.core.ApplicationDispatcher.processRequest
(ApplicationDispatcher.java:463)
at org.apache.catalina.core.ApplicationDispatcher.doForward
(ApplicationDispatcher.java:399)
at org.apache.catalina.core.ApplicationDispatcher.forward
(ApplicationDispatcher.java:301)
at org.apache.catalina.core.StandardHostValve.custom
(StandardHostValve.java:364)
at org.apache.catalina.core.StandardHostValve.status
(StandardHostValve.java:285)
at org.apache.catalina.core.StandardHostValve.throwable
(StandardHostValve.java:229)
at org.apache.catalina.core.StandardHostValve.invoke
(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke
(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke
(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service
(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process
(Http11Processor.java:875)
at org.apache.coyote.http11.Http11BaseProtocol
$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:
665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket
(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt
(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run
(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:595)


On 2월2일, 오후3시22분, 선영욱 <twinmoon2...@gmail.com> wrote:
> 안녕하세요.
>
> 다름이 아니라 Spring 2.5 + iBatis + DWR + SiteMash 의 구성으로 만든 웹 어플리케이션이 하나 있습니다.
>
> 그런데 보안심사 과정에서 스트레스 테스트 처럼 Requst를 사이트 전반적으로 요청을 하는 과정에서 웹 어플리케이션에서 out of
> memory 오류가 발생하였습니다.
>
> 2010. 1. 29 오후 1:03:21 org.apache.tomcat.util.http.Parameters
> processParameters
> 경고: Parameters: Invalid chunk ignored.
> 2010. 1. 29 오후 1:03:28 org.apache.catalina.connector.CoyoteAdapter service
> 심각: An exception or error occurred in the container during the request
> processing
> java.lang.OutOfMemoryError: Java heap space
> at java.io.BufferedReader.<init>(BufferedReader.java:80)
> at java.io.BufferedReader.<init>(BufferedReader.java:91)
> at java.io.LineNumberReader.<init>(LineNumberReader.java:52)
> at

> org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep(ThrowableInfor-mation.java:78)


> at
> org.apache.log4j.spi.LoggingEvent.getThrowableStrRep(LoggingEvent.java:407)
> at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:305)
> at

> org.apache.log4j.RollingFileAppender.subAppend(RollingFileAppender.java:263-)


> at org.apache.log4j.WriterAppender.append(WriterAppender.java:160)
> at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
> at

> org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(Appen-derAttachableImpl.java:66)


> at org.apache.log4j.Category.callAppenders(Category.java:206)
> at org.apache.log4j.Category.forcedLog(Category.java:391)
> at org.apache.log4j.Category.log(Category.java:856)
> at org.apache.commons.logging.impl.Log4JLogger.error(Log4JLogger.java:257)
> at

> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.j-ava:253)
> at
> org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.j-ava:172)
> at
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:12-7)
> at
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:11-7)
> at
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.jav-a:108)


> at
> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
> at
> org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
> at

> org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.process-Connection(Http11BaseProtocol.java:665)
> at
> org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.ja-va:528)
> at
> org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerW-orkerThread.java:81)
> at
> org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.ja-va:689)

박성철

unread,
Feb 2, 2010, 1:41:27 AM2/2/10
to ks...@googlegroups.com
WAS(tomcat을 사용하시는 듯) 띄우실 때 JVM 옵션으로 heap size를 몇으로 주
셨나요?

여기 문서를 참고하십시오.
http://www.chemaxon.com/jchem/doc/admin/tomcat.html

선영욱

unread,
Feb 2, 2010, 2:06:45 AM2/2/10
to ks...@googlegroups.com
제가 직접 셋팅한 부분은 아니라서 적용이 되었는지 모르겠지만, 다음과 같이 셋팅했습니다.
 
CATALINA_OPTS= -XX:MaxPermSize=128m;-Xms256m;-Xmx1024m
 
1024 정도면 보통 어느정도 버틸 수 있지 않을까 싶은데요.
 
조금 더 많이 준다면 이슈가 해결 될 수 있을까요?

2010년 2월 2일 오후 3:41, 박성철 <gyu...@gmail.com>님의 말:
--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.


kuwon Kang

unread,
Feb 2, 2010, 2:32:30 AM2/2/10
to ks...@googlegroups.com
메모리를 더 늘린다고 해결될 문제처럼 보이지 않습니다.

일단 아래 사항을 코드 리뷰를 통해 점검해 보시면 좋을 것 같습니다.

1. 모든 Stream관련 객체는 Close 되었는가?
   가능한 아래와 같이 finally로 처리하는게 좋습니다.

   try
   { 
     stream 사용
   } finally {
     if(stream != null)
        stream.close();
   }

2. List, Map객체에 계속적으로 add/put되는 코드는 존재하지 않는가?
  보통 Member Field로 선언된 타입중 Map, List가 있는데 많이 실 수하는 것이
  이 멤버 필드를 사용하는 메서드에서 remove를 하지 않고 실수로 계속 추가만 하는 
  코드들이 있습니다. 논리적으로 add만 계속하도록 의도할 수 있지만 정말 그런지?
  request가 있을 때마다 계속 요청되고 있지는 않은지? 체크해보셔야 할 것 같아요.

  논리적으로 Tomcat에서 수행되는 web App는 스프링으로 작성하셨다면
  아마도 Singleton일 것 같은데요 그 클래스중 멤버 필드중 Map, List를 사용하여 Add만 하고 
  remove하지 않는 코드가 있는지 한번 살펴보시는게 좋을 것 같아요.

감사합니다.


2010/2/2 선영욱 <twinmo...@gmail.com>
 
 

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.



--
Blessings.
Kuwon Kang
............................................................
IT specialist and architect.
Java technology engineer.
JavaEE architect/developer.
Solution developer.

- Model Driven Architecture.
- Test Driven Development.
- Refactoring Oriented Development.
- Practical design and modeling.
- Robust  Software Design and Engineering.
............................................................
Prever
http://www.prever.co.kr
Blog:
http://www.prever.co.kr/josh
............................................................

선영욱

unread,
Feb 2, 2010, 4:25:16 AM2/2/10
to ks...@googlegroups.com
좋은 조언 감사드립니다.
 
 먼저 소스 코드에서 말씀하신 내용을 면밀하게 검토해 보겠습니다.
 
그리고 비슷한 상황을 재현해 보려면 JMeter 같은 것으로 테스트가 가능할까요?

2010년 2월 2일 오후 4:32, kuwon Kang <preve...@gmail.com>님의 말:

Sanghyuk Jung

unread,
Feb 2, 2010, 4:35:49 AM2/2/10
to ks...@googlegroups.com
 리플랙션과 관련된 영역은 Perm영역이라서 아마 메시지가 위와는 다르게 나올듯합니다.
 
 heap dump를 떠보셔서 어느 객체가 가장 커져 있는지 확인을 해야지 풀리는 문제일지도 모릅니다.
 
덤프파일 만드셔서 Eclipse Memory Analyzer같은 것을 사용하시면 도움이 되실듯합니다.
 


 
2010년 2월 2일 오후 4:32, kuwon Kang <preve...@gmail.com>님의 말:
메모리를 더 늘린다고 해결될 문제처럼 보이지 않습니다.

kuwon Kang

unread,
Feb 2, 2010, 4:54:03 AM2/2/10
to ks...@googlegroups.com
물론입니다.

JMeter같은 간단한 스트레스 생성기로 돌리셔도 됩니다.

Load Runner는 상용툴이니 그런 경우는 좀 어려울 것 같구요.

다만 메모리 릭을 찾기 위해서는 실제 상황과 같은 테스트 환경 구성이 우선입니다.

경험상 대부분 OpenSource의 메모리 릭보다는 사용자 실수로 인한 메모리 릭이 대부분이라고 보는 것이 좋을 것 같습니다.

물론 가끔 오픈소스 패치가 필요한 경우가 있습니다.
스프링의 경우 Context Destroy에서 호출해야 하는 케이스도 있고, CGLib는 최신 걸로 사용해야 하는 경우 도 있고.

근데 지금 경우는 아마도 Web Context가 계속 적으로 리로드 되는 경우가 아니라면 실제 사용자 코드가 원인인 경우가 많습니다.

근데 이렇게 리뷰를 통해 고쳐진 코드를 반영해도 릭이 발생한다면 최종적으로는 DUMP를 떠서 비교해보시는 방법밖에는 없어 보입니다.

그럼 고생하십시요~~

아 마지막으로 체크 리스트 하나 빠졌는데요 혹시 ThreadLocal을 사용하신다면 반드시 request가 끝나는 시점에서 remove해주셔야 합니다.


2010/2/2 선영욱 <twinmo...@gmail.com>

Sewon Ann

unread,
Feb 2, 2010, 5:44:33 AM2/2/10
to ks...@googlegroups.com
간단하게는 JDK 에 들어있는 JConsole 을 사용하셔서 profiling 을 해 보실 수도 있습니다. 도움이 되더라고요.

http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html

어느 블로거께서 tomcat 연결방법을 적어두셨군요.
http://cacky.tistory.com/39

java power tools 라는 책을 보셔도 나옵니다.
http://www.wakaleo.com/java-power-tools

모쪼록 메모리가 새는 구멍이 있었다면 쉽게 찾으시길 ^^


2010/2/2 kuwon Kang <preve...@gmail.com>

서철

unread,
Feb 16, 2010, 2:49:03 AM2/16/10
to ks...@googlegroups.com

안녕하세요?

이거 공유하는 방법을 몰라서 ksug에서 찾다가 그냥 답변 메일로 글 쓰네요.

 

저도 같은 경험이 있어서 글 드립니다.

 

아래 좋은 글들도 참고 하시고요.

저 같은 경우도 같은 메모리 에러가 있었는데요.

 

[제 경우 환경]

 

WAS : Tomcat 6.0

서버 : Window 2008 Server

 

서버의 물리 메모리를 확인 후 적정한 메모리를 할당하시면 될 듯합니다.

실제로 할당해보니 1GB 인가 넘어서는 할당할 수 없다는 메시지를 본 듯도 한데 기억이 가물 -.-;

 

heap 메모리 확장 할당을 startup.bat에

CATALINA_OPTS= -XX:MaxPermSize=128m;-Xms256m;-Xmx1024m 이렇게 할당해 봤는데 적용이 안되더군요.

동일한 오류가 발생하였습니다. 확인하는 방법은 해당 메모리를 설정하지 않고 작업관리자를 띄우고 메모리 변화를 지켜보시면 알 수 있습니다.

변화가 없습니다.

 

그래서 찾다 보니까 톰캣의 설정화일들을 디적거리다보니 %CATALINA_OPTS% 이 문구를 여러개 발견했습니다.

이게 우리가 환경변수 설정할 때 많이 사용하는 거잖아요?

그래서 혹시나 싶어 환경변수에 아래와 같이 추가해 보고 톰캣을 재구동해보니 메모리가 올라가는 것이 확인되었고,

더이상 java.lang.OutOfMemoryError: Java heap space 에러는 발생하지 않았습니다.

 

환경변수명 : CATALINA_OPTS

값 : -XX:MaxPermSize=128m;-Xms256m;-Xmx1024m

 

값의 수치들은 조정을 요리 조리 해보시고요.

 

참고로 님께서는 스프링을 사용하시니 이 제 경우와 같은 실수는 없으시리라 보는데요.

 

한가지 제 경우의 잘못 설정한 경우가 있었는데 iBatis 의 SqlMapConfig.xml 파일(아래)에서 <dataSource type="SIMPLE"> 부분인데요.

예전에 <dataSource type="DBCP"> 로 설정했다가 ConnectionPool 이 잘 관리가 되질 않아 연결이 계속 죽은 적도 있었습니다.

혹시나 저 같은 실수를 하셨으면 참고하시라고 같이 적어봅니다.

 

그럼 즐거운 하루 되십시요 ^^;

 

---  SqlMapConfig.xml 파일의 dataSource 설정 부분 (참고자료) -----------------------

 

  <transactionManager type="JDBC">
   <dataSource type="SIMPLE">
    <property name="JDBC.Driver" value="${jdbc.driver}"/>
    <property name="JDBC.ConnectionURL" value="${jdbc.url}"/>
    <property name="JDBC.Username" value="${jdbc.user}"/>
    <property name="JDBC.Password" value="${jdbc.password}"/>
    <property name="Pool.MaximumActiveConnections" value="${pool.maxConn}"/>
    <property name="JDBC.MaxIdle" value="${jdbc.maxIdle}"/>
   </dataSource>

 

PS.근데 이거 어디서 글 쓰면 이렇게 다 공유되나요?

무식한 사용자가 첨으로 답변하나 변변히 못달면서 문의 드려봅니다.

 

원상호

unread,
Feb 16, 2010, 3:05:09 AM2/16/10
to ks...@googlegroups.com
본인의 메일 클라이언트에서 회신하기만 하면 됩니다. 그러면 수신 주소가 ks...@googlegroups.com로 되고
ks...@googlegroups.com이 메일을 수신하면 전체 구독자에게 메일이 갑니다.

2010/2/16 서철 <myme...@naver.com>
Reply all
Reply to author
Forward
0 new messages