반응형

 


 월 초(15.01)에 현재 팀에 분산 되어 있는 빌드 및 CI 서버 통합 작업을 진행하였다. 이번 포스팅은 서버 통합 작업을 하다가 발생한 java.lang.OutOfMemoryError: PermGen space문제에 대해 알아보도록 하겠다. 먼저 첫 번째로 문제가 발생한 현상에 대해 살펴보고 둘 째, 어떻게 해결했는지 살펴보고 마지막 셋째, java.lang.OutOfMemoryError: PermGen space에 대해 자세히 알아보자.



 1. 서버 작업 중 발생한 현상


 기존 서버에서 빌드 되는 프로젝트들도 많았지만 (약 50개 정도) 해당 부분에 대해서는 많은 문제가 되지 않았다. 왜냐하면 여러 프로젝트(10개 이상)가 동시에 빌드 작업을 진행하는 경우는 제로에 가까웠기 때문이다. 문제는 특정 소스코드가 수행되었을 때 자동으로 빌드되 commit_build와 특정 시간 간격마다 수행되게 하는 배치 빌드 등을 추가하면서 부터 발생하였다. 처음에는 서버 통합작업을 잘 진행하고 있었는데 어느 순간 부터(c_build, i_build)가 여러 개 추가되는 시점부터 서버가 뻗어버리는 현상이 발생하였다. 


 


 다음 그림과 같이 java.lang.OutOfMemoryError: PermGen space 에러가 발생한 것을 볼 수 있다. 이로 인해 서버가 뻗어 버리는 현상이 주기적(약1시간 간격)으로 나타났다. 그래서 일차적으로 주기적으로 빌드 되는 프로젝트들에 대해 주기적으로 빌드 되지 않도록 작업하였다.



  2. 해결한 방법

먼저 해결책을 말하자면 해당 서버의 톰캣/bin catalina.sh 에 들어가서 밑의 그림과 같이 추가해주었다.

 

그림이 잘 안보인다 ㅠㅠ 아무튼

 JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:MaxPermSize=512m -XX:-UseConcMarkSweepGC"

를 선언해주어 해결하였다. (기존에는 -XX:MaxPermSize가 선언되어 있지 않았다. (기본 20m로 설정되있다고 한다)


# -XX:+UseConcMarkSweepGC

 // 표준 garbage collector가 아닌 perm gen도 gc하는 concurrent collector를 사용하도록 한다.


-XX:+CMSPermGenSweepingEnabled

 // perm gen 영역도 gc의 대상이 되도록 한다.


-XX:+CMSClassUnloadingEnabled

// 클래스 데이타도 gc의 대상이 되도록 한다.


# -XX:MaxPermSize=64m

// 어느정도 크기가되어야 gc가 자주 발생하지 않는다. 기본값이 8M인듯.




  3. java.lang.OutOfMemoryError: PermGen space 관련 정보들에 대해 알아보자. (두서 없이 정리됨을 양해바람)


# java.lang.OutOfMemoryError: PermGen space문제는 기본적으로 동적 클래스를 많이 사용할 경우 빈번히 발생하는 문제로 JSP->SERVLET 변화. SPIRNG에서의 동적 클래스를 많이 사용하는 프레임워크로 인해 발생한다.


# JVM이 새로운 클래스 정의를 로드해야 하는데 이를 수행하기 위한 PerGen 공간이 충분하지 않아 발생한다. 즉, 이미 너무 많은 클래스들이 로딩되어 있으며 서버가 현재 크기의 PermGen이 처리할 수 없을 만큼 많은 클래스들을 사용하고 있기 때문이기도 하다. 


# 보통 Java heap이나 힙의 특정 영역에 객체를 할당 할 수 있는 공간이 충분하지 않을 때 발생


# PermGen space 라는 메시지는 permanent generation 이 가득 찬 상태라는 것을 알려준다. permanent generation은 클래스와 메쏘드 객체가 저장되는 힙의 영역을 나타낸다. 어플리케이션이 많은 수의 클래스를 로드하면, -XX:MaxPermSize 옵션을 사용하여 permanent generation의 크기를 증가시킬 필요가 있다. 


# 보통 톰캣을 사용하다가 이 에러를 보았다면 대체로 웹 어플리케이션을 너무 많이 Update 하거나 Reload 한 것이 원인이 될 수 있다. 톰캣과 JVM은 웹 어플리케이션을 삭제하고 다시 생성할 때 할당한 모든 메모리를 해제하지는 않는다. 톰캣을 여러 번 리로드 하면 할당된 메모리가 바닥나서 동작하지 않게 된다. 


# 톰캣에서 이 에러가 발생했을 경우 해결 방법은 1. 톰캣을 재시작 하는 것(임시적으로 해결) 2. 톰캣이 할당할 수 있는 메모리를 늘려 준다. 3. 메모리 누수가 발생하지 않도록 톰캣을 설정 (불필요한 프로젝트 들이 로딩되지 않도록 정리)


# Heap은 프로그램이 돌아가는 도중에 생성 삭제되는 곳으로 garbage-collected가 일어나는 곳이며 Permenant는 프로그램이 끝날 때까지 영원히 메모리를 차지하고 있는 공간으로 garbage-collected가 일어나지 않는 곳이다. Heap에는 동적으로 생기는 메모리 들이 들어가는 곳이고, Permenanat는 Class names, Internalized strings, Objects 등이 들어가며 PermGen도 이곳에 해당한다. 


참조 :

http://mindasom.tistory.com/96

http://jwchoi85.tistory.com/155#recentComments





반응형

+ Recent posts