상세 컨텐츠

본문 제목

PermGen OutOfMemoryError

프로그래밍/JAVA

by 라제폰 2011. 7. 22. 15:23

본문


JVM에는 메모리 영역이 몇개 있다. 그 중 PermGen 영역은 영구한 생명은 얻은 데이타가 놓이는 곳이다. 영구한 생명을 얻은 만큼 gc의 대상이 되지 않는다. 그런데 이곳이 가득차 버리면 다음과 같은 에러가 던져진다.
   java.lang.OutOfMemoryError: PermGen space failure"

클래스의 인스턴스가 아닌 클래스 자체에 대한 정보는 PermGen영역에 놓인다.

WAS에 웹 어플리케이션을 반복적으로 배치할 경우, WAS는 기존 웹 어플리케이션을 로딩한 class loader를 파기하고 새로운 class loader를 가지고 새로 배치된 웨 어플리케이션의 클래스를 새로 로딩한다. 그런데 기존의 class loader를 파기했다하더라고 이미 PermGen 영역에 있는 클래스들에 대한 정보는 회수하지 않는다. 결국 계속 쌓이게 되고 결국 위의 에러를 내뱉으며 WAS가 죽게 된다.

이러한 현상은 WAS나 특정 라이브러리 혹은 java code의 문제가 아닌 JVM들의 특성이다.

단 다음과 같은 jvm 옵션을 가지고 gc가 가능하다.
  -XX:+UseConcMarkSweepGC
   // 표준 garbage collector가 아닌 perm gen도 gc하는 concurrent collector를 사용하도록 한다.
  -XX:+CMSPermGenSweepingEnabled
   // perm gen 영역도 gc의 대상이 되도록 한다.
  -XX:+CMSClassUnloadingEnabled
   // 클래스 데이타도 gc의 대상이 되도록 한다.
  -XX:MaxPermSize=64m
   // 어느정도 크기가되어야 gc가 자주 발생하지 않는다. 기본값이 8M인듯.

from : http://my.opera.com/karmazilla/blog/2007/03/13/good-riddance-permgen-outofmemoryerror

그러나 XX 옵션인 만큼 표준 옵션이 아니고 모든 JVM에서 동작하는 지는 보장할 수 없다.

테스트 해보면 옵션이 없을 때 아예 GC가 안되는 것에 비해, GC가 되기는 하지만 믿을 수 있을 만큼 제대로! GC가 되지는 않는듯 하다. 에러가 발생하는 것 자체를 막지는 못한다.



참고로 다음과 같은 코드로 메모리 상태를 볼 수 있다. 1.5 이상에서만.
for (java.lang.management.MemoryPoolMXBean mx : java.lang.management.ManagementFactory.getMemoryPoolMXBeans()) {
  System.out.println(mx.getName()+" : "+mx.getUsage());
}


Code Cache : init = 196608(192K) used = 1024448(1000K) committed = 1048576(1024K) max = 33554432(32768K)
Eden Space : init = 33030144(32256K) used = 660784(645K) committed = 33030144(32256K) max = 33030144(32256K)
Survivor Space : init = 4128768(4032K) used = 0(0K) committed = 4128768(4032K) max = 4128768(4032K)
Tenured Gen : init = 495583232(483968K) used = 6596272(6441K) committed = 495583232(483968K) max = 495583232(483968K)
Perm Gen : init = 8388608(8192K) used = 3704584(3617K) committed = 8388608(8192K) max = 8388608(8192K)
Perm Gen [shared-ro] : init = 8388608(8192K) used = 5645888(5513K) committed = 8388608(8192K) max = 8388608(8192K)
Perm Gen [shared-rw] : init = 12582912(12288K) used = 5961888(5822K) committed = 12582912(12288K) max = 12582912(12288K)

관련글 더보기