JAVA GC overhead limit exceeded

Kevin·2024년 3월 26일
0

Trouble Shooting

목록 보기
4/7
post-thumbnail

서론

어제 퇴근 하기 전 갑작스럽게 전화가 한 통 걸려왔었다.

전화를 받아보니, 지금 WAS Server에 보내는 요청이 너무 오래걸려서 Time Out이 계속해서 발생한다는 것이다.

급하게 서버에 접근해서 로그를 살펴보니 아래와 같은 에러가 지속적으로 출력 되고 있었다.

Could not open JDBC Connection for transaction; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded

위 에러의 뜻과 어떻게 해결해야 하는지, 그리고 나는 이 에러를 어떻게 해결했는지에 대해서 알아보도록 하자.


GC overhead limit exceeded

Could not open JDBC Connection for transaction; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded

먼저 위 에러의 뜻은 현재 JVM이 가바지 컬렉션을 수행하는데 있어서 너무 많은 시간을 소비하고 있으며, 아주 적은 힙 공간만 회수할 수 있기에, JDBC 커넥션을 생성할 수 있는 동적 메모리가 부족하다는 뜻이다.

이 때 일반적으로 해당 JAVA 프로그램의 속도는 극도로 느려지는데, 이 이유는 JAVA 프로세스가 GC를 수행하는데 98% 이상을 소비하고, Heap의 2% 미만만 복구하기 때문이다.

더 자세히는 GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread는 멈추게 되어서 STW(Stop The World) 현상이 일어나기 때문에 속도가 급속도록 느려지는 것이다.

그렇다면 어떻게 이 에러를 해결할 수 있는가?

가장 간단한 방법으로는 JVM에 할당되는 Heap 크기를 늘리면 된다.

Tomcat 디렉토리의 catalina.sh 파일에서 JAVA_OPTS 부분을 아래와 같이 수정하면 된다.


JAVA_OPTS="$JAVA_OPTS -Xms1024m -Xmx1024m $JSSE_OPTS"

→ Xms는 최소 힙영역 크기 -Xmx는 최대 힙영역 크기 값이다.

수정 후 톰캣을 재구동하면 이 수정 사항이 반영될 것이다.

그러나 이는 완전한 해결 방법이라기 보다는 문제를 뒤로 미루는 것에 가깝다.

우아한 기술 블로그에 따르면 Heap Dump를 통해서 상태를 분석하는 방법이 있다고 한다.

이 때 Heap Dump란 장애가 발생했을 때의 Heap 상태를 기록으로 남겨서, 그 당시에 어떤 JAVA 객체들이 많이 만들어졌는지에 대해서 분석하는 로그 파일이다.

Heap Dump에 대해서 잘 정리한 글

또한 ngrinder이나 성능 측정 프로그램을 사용하여서, 현재 JAVA 프로젝트 내에서 Memory가 지속적으로 Leak이 발생하는 부분을 찾아서 수정하는 것을 추천하였다.

그렇다면 내가 적용한 방법은 무엇일까?

JVM에 할당되는 Heap 크기를 늘리는 방식을 사용하였다.

위에서 이 방식을 추천하지 않으면서 사용했던 이유는 2가지인데,

첫번째로는 지금 당장 GC overhead limit exceeded 문제를 슈팅 해야하는 시간적인 이유와 두번째로는 서버에 올려져있는 애플리케이션 단 코드를 건들기 위해서는 SVN 관련 작업이 수반되어야 했기 때문이다.

일단 급한 불은 껐으니 위에서 다룬 방법들로 문제를 해결 해보아야겠다.

profile
Hello, World! \n

0개의 댓글