📦 Tomcat Out of Memory (OOM) 오류
1. Out of Memory (OOM) 오류란?
Out of Memory (OOM) 오류는 **JVM (Java Virtual Machine)**이 할당된 메모리 용량을 초과해 더 이상 메모리를 할당할 수 없을 때 발생하는 오류입니다.
Tomcat 서버에서 자주 발생하는 OOM 오류는 대개 Java 애플리케이션이 너무 많은 메모리를 소비하거나 JVM의 메모리 설정이 부족할 때 나타납니다.
2. OOM 오류의 주요 원인
2.1. JVM 메모리 설정 부족
Tomcat은 Java 기반의 웹 서버이므로, JVM의 메모리 설정이 부족할 경우 애플리케이션이 사용할 수 있는 메모리가 부족해져서 OOM이 발생할 수 있습니다.
JVM에는 여러 종류의 메모리 영역이 있는데, 그 중 가장 중요한 두 가지는 **힙 메모리(heap memory)**와 **메타스페이스(Metaspace)**입니다.
- 힙 메모리 (Heap Memory): 애플리케이션에서 사용하는 객체들이 저장되는 메모리 공간.
- 메타스페이스 (Metaspace): 클래스 메타데이터가 저장되는 공간.
2.2. 메모리 누수 (Memory Leak)
애플리케이션에서 메모리 할당 후 해제되지 않거나, 필요 없는 객체를 계속해서 생성하고 해제하지 않으면 메모리 누수가 발생합니다.
이로 인해 시간이 지남에 따라 점점 더 많은 메모리를 소비하게 되어 OOM이 발생할 수 있습니다.
2.3. 불필요한 스레드 또는 연결
Tomcat에서 너무 많은 스레드나 DB 연결이 생성되면 메모리를 과도하게 소모하게 되어 OOM 오류가 발생할 수 있습니다.
3. Out of Memory (OOM) 오류 해결 방안
3.1. JVM 메모리 설정 변경
Tomcat이 실행되는 JVM의 힙 메모리, 메타스페이스 등을 조정하여 메모리 부족을 방지할 수 있습니다.
- Tomcat에서 JVM 메모리 설정을 변경하는 방법: Tomcat의 메모리 설정은 $CATALINA_HOME/bin/setenv.sh (Linux/Unix) 또는 setenv.bat (Windows) 파일에서 설정할 수 있습니다.
예시: setenv.sh 파일 수정
export CATALINA_OPTS="-Xms512m -Xmx2048m -XX:MaxMetaspaceSize=512m"
- -Xms512m: 초기 힙 메모리 크기 (512MB)
- -Xmx2048m: 최대 힙 메모리 크기 (2048MB, 즉 2GB)
- -XX:MaxMetaspaceSize=512m: 메타스페이스의 최대 크기 (512MB)
메모리 설정을 충분히 커지면 OOM을 예방할 수 있습니다. 그러나 너무 큰 값을 설정하면 시스템에 과도한 부담을 줄 수 있으므로 적절히 설정해야 합니다.
3.2. 메모리 누수 해결
메모리 누수는 대부분 코드에서 객체를 적절히 해제하지 않거나, 비효율적인 메모리 관리로 인해 발생합니다. 이를 해결하려면:
- 애플리케이션 코드 검토: 객체를 다 사용한 후 명시적으로 null로 설정하거나, try-with-resources 구문을 사용하여 리소스를 자동으로 해제하도록 합니다.
- 메모리 분석 도구 사용: VisualVM, Eclipse Memory Analyzer, jmap 등을 사용하여 메모리 사용 현황을 분석하고 메모리 누수 원인을 추적합니다.
예시:
jmap -heap <PID> # JVM 힙 메모리 분석
- GC 로그 분석: -XX:+PrintGCDetails -XX:+PrintGCDateStamps 옵션을 사용하여 GC 로그를 확인하고, 메모리 누수나 과도한 가비지 컬렉션을 찾아낼 수 있습니다.
3.3. 불필요한 스레드/DB 연결 관리
Tomcat에서 스레드 풀이나 DB 연결 풀의 크기를 너무 크게 설정하면 메모리 부족을 초래할 수 있습니다.
- 스레드 수 제한: Tomcat의 server.xml 파일에서 Connector 태그 내의 maxThreads 값을 적절하게 설정하여 처리할 수 있는 요청의 수를 제한합니다.
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200" />
- DB 연결 풀 설정: DB 연결을 잘 관리하지 않으면 불필요한 연결이 쌓여서 메모리 문제를 일으킬 수 있습니다. Tomcat JDBC Connection Pool을 사용하여 커넥션 풀의 최대 크기(maxActive)와 최소 크기(minIdle)를 설정할 수 있습니다.
<Context>
<Resource name="jdbc/myDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
minIdle="10"
username="dbuser"
password="dbpassword"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb" />
</Context>
3.4. JVM 옵션 추가
Tomcat의 성능을 최적화하기 위해 다양한 JVM 옵션을 추가할 수 있습니다.
- 가비지 컬렉션 옵션 추가:G1 GC는 대형 힙을 가진 애플리케이션에 유리한 가비지 컬렉션 방식입니다. GC로 인한 OOM을 방지할 수 있습니다.
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
- Heap Dump 설정: OOM이 발생했을 때 Heap Dump를 자동으로 생성하여 원인 분석에 도움을 줄 수 있습니다.
export CATALINA_OPTS="$CATALINA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/heapdump.hprof"
4. 로그 분석 및 모니터링 도구 사용
- JVM 로그 분석 도구: jstat, jmap 등을 사용하여 힙 메모리와 GC 동작을 분석할 수 있습니다.
- 성능 모니터링 도구:
- VisualVM: JVM 성능 분석 도구로 메모리 사용량, CPU 사용량, GC 상태 등을 모니터링합니다.
- New Relic, Datadog 등 APM(Application Performance Management) 도구를 사용하여 애플리케이션의 메모리 사용 현황을 실시간으로 모니터링합니다.
5. 요약
원인 | 해결 방안 |
JVM 메모리 설정 부족 | setenv.sh에서 -Xms, -Xmx 설정 조정 |
메모리 누수 | 코드 검토 및 메모리 분석 도구 사용 (VisualVM, Eclipse MAT 등) |
스레드/DB 연결 관리 불량 | server.xml의 maxThreads 및 DB 연결 풀 설정 최적화 |
가비지 컬렉션 이슈 | G1 GC 및 JVM 옵션 추가 |
OOM 발생 시 분석 필요 | Heap Dump, GC 로그 활성화 및 분석 도구 사용 |
6. OOM 발생 시 catalina.out 로그에 나타나는 내용
catalina.out 파일에는 JVM의 메모리 부족, 가비지 컬렉션 상태, 그리고 OOM 오류와 관련된 정보가 기록됩니다. OOM이 발생할 때 발생하는 일반적인 로그 항목은 다음과 같습니다.
예시 로그:
java.lang.OutOfMemoryError: Java heap space
at java.util.ArrayList.ensureCapacity(ArrayList.java:169)
at java.util.ArrayList.add(ArrayList.java:353)
at com.example.myapp.SomeClass.someMethod(SomeClass.java:45)
at com.example.myapp.MainClass.main(MainClass.java:12)
...
이 로그는 Java heap space 메모리 부족으로 인한 OOM 오류를 보여줍니다. 이는 힙 메모리가 부족하여 더 이상 객체를 할당할 수 없을 때 발생합니다.
7. OOM 관련 예시 로그 항목
- Out of Memory Error (heap space):
java.lang.OutOfMemoryError: Java heap space
- Metaspace 부족으로 인한 OOM:
java.lang.OutOfMemoryError: Metaspace
- GC 로그가 함께 나오는 경우: OOM 오류가 발생하기 전에 가비지 컬렉션이 얼마나 이루어졌는지 확인할 수 있습니다.
[GC (Allocation Failure) 123456K->1234K(2048K), 0.0023456 secs]
[GC (Allocation Failure) 123456K->1234K(2048K), 0.0023456 secs]
8. OOM 오류 발생 후 흔히 나오는 GC 관련 로그
JVM은 메모리를 회수하기 위해 가비지 컬렉션(GC) 을 수행하는데, OOM 오류가 발생하기 전에 가비지 컬렉션이 발생하는 경우가 많습니다. 이때 GC의 로그가 포함될 수 있습니다.
예시:
[GC (Allocation Failure) 123456K->1234K(2048K), 0.0023456 secs]
[GC (Allocation Failure) 123456K->1234K(2048K), 0.0023456 secs]
이 로그에서는 GC가 실패했거나 메모리가 회수되지 않았음을 나타냅니다. OOM이 발생할 때마다 GC가 적절히 메모리를 회수하지 못하면 결국 OOM 오류로 이어집니다.
9. Out of Memory와 관련된 로그 패턴
- OutOfMemoryError 메시지가 발생하면, StackTrace와 함께 오류가 발생한 클래스와 메서드 정보가 기록됩니다. 이를 통해 메모리 소비가 많아지는 위치를 확인할 수 있습니다.
- GC 로그는 가비지 컬렉션이 얼마나 자주 수행되었고, 얼마나 메모리를 회수했는지에 대한 정보를 제공합니다.
- 클래스 로딩 및 언로딩 문제가 메타스페이스 부족으로 OOM을 일으킬 수 있으므로, 메타스페이스 관련 오류가 있다면 JVM의 메타스페이스 설정을 조정해야 합니다.
10. OOM 로그 분석 방법
OOM 로그를 분석할 때는 다음과 같은 절차로 진행할 수 있습니다:
10.1. Stack Trace 분석
- Stack Trace에서 오류가 발생한 지점(클래스와 메서드)을 추적하여 메모리 할당이 많은 곳을 찾아냅니다.
- 특정 객체가 너무 많이 할당되고 있거나, 특정 메서드에서 반복적으로 메모리 할당이 발생하고 있는지 확인합니다.
10.2. GC 로그 분석
- 가비지 컬렉션을 확인하여 메모리가 얼마나 회수되었는지 확인하고, GC가 제대로 동작하지 않거나 자주 발생하는지 점검합니다.
- GC 시간이 너무 길어지면 애플리케이션이 느려지거나 OOM을 유발할 수 있습니다. -XX:+PrintGCDetails 옵션을 사용하여 GC 상태를 더욱 세밀하게 분석할 수 있습니다.
10.3. Heap Dump
OOM이 발생할 때 Heap Dump를 생성하는 설정을 추가하면, 메모리 덤프 파일을 분석하여 메모리 누수 문제를 더 잘 파악할 수 있습니다. -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumpfile 옵션을 사용하여 자동으로 덤프 파일을 생성하게 할 수 있습니다.
export CATALINA_OPTS="$CATALINA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/heapdump.hprof"
11. catalina.out 로그에서의 OOM 관련 예시
- 메모리 부족(Heap space) 예시:
java.lang.OutOfMemoryError: Java heap space
at java.util.ArrayList.ensureCapacity(ArrayList.java:169)
at java.util.ArrayList.add(ArrayList.java:353)
at com.example.myapp.SomeClass.someMethod(SomeClass.java:45)
at com.example.myapp.MainClass.main(MainClass.java:12)
- 메타스페이스 부족 예시:
java.lang.OutOfMemoryError: Metaspace
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:235)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:156)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:141)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:129)
12. 로그 파일 위치
Tomcat의 catalina.out 파일은 Tomcat 로그 디렉토리에 저장됩니다. 일반적으로 Tomcat의 로그는 /logs 디렉토리에 저장됩니다.
- 로그 경로 예시:
-
/path/to/tomcat/logs/catalina.out
13. 요약
- OOM 발생 시 catalina.out 로그에 OutOfMemoryError 또는 GC 로그가 포함됩니다.
- 메모리 부족 문제를 해결하려면 JVM 메모리 설정, 메모리 누수 분석, GC 로그 분석, Heap Dump 분석을 통해 원인을 추적할 수 있습니다.
- Heap Dump와 GC 로그 분석을 통해 애플리케이션에서의 메모리 소비 문제를 해결할 수 있습니다.
'OS' 카테고리의 다른 글
[Linux] Error in queuecommand_lck: us->srb = ffff8801b252b6 에러 분석 (0) | 2025.04.29 |
---|---|
[Linux] 커널패닉(Kernel Panic)이란? (0) | 2025.04.29 |
[Linux] Oracle Listener 와 Tnsname 개념 정리 (0) | 2025.04.29 |
[Linux] Chrony 설정하는 방법 (0) | 2025.04.29 |
[Windows] Win + R 실행창 유용 명령어 모음 (1) | 2025.04.29 |