잊지 않겠습니다.

(원문 : http://javaeesupportpatterns.blogspot.ie/2013/02/java-8-from-permgen-to-metaspace.html)

Java8에서 가장 큰 변화라고 개인적으로 생각하고 있는 Metaspace에 대한 post를 한번 번역해서 소개합니다.

JDK7까지 사용된 Permanent General (PermGen) space가 Oracle의 주도하에 제거된 것이 큰 특징중 하나입니다. 예를 들어, 내부 문자열의 경우, JDK7에서 이미 제거되어있었으나, JDK8에서 최종적으로 폐기되게 되었습니다.

이 문서는 PermGen의 후계자라고 할 수 있는 Metaspace에 대한 내용입니다. 또한 우리는 HotSpot 1.7 vs HotSpot 1.8 간의 leaking class meta object의 동작에 대해서 알아보도록 하겠습니다.

Metaspace : 새로운 메모리 저장소의 탄생

JDK8 HostSpot VM의 경우, 재사용성을 위한 객체에 대한 metadata를 Metaspace라고 불리우는 native memory에 저장하게 됩니다. 마치 Oracle JRockit 또는 IBM JVM과 같은 동작으로 구성되게 됩니다.

좋은 뉴스는 이제는 더이상 java.lang.OutOfMemoryError : PermGen space와 같은 문제를 더이상 야기하지 않는다는 것과 더이상 tunning과 monitoring을 통해서 이러한 memory space를 조절할 필요가 없다는 것입니다. 그렇지만, 이러한 변화는 기본적으로 안보이게 설정이 되기 때문에 우리는 이 새로운 meta memory에 대한 족적을 여전히 살펴볼 필요성은 존재하게 됩니다. 이러한 변화가 마법과 같이 class의 메모리 공간을 줄여주거나 class loader의 memory leak을 줄여주지는 못하는 것을 인지해야지 됩니다. 우리는 새로운 naming convention하에서 다른 시각으로 이러한 문제를 바라보는 것이 필요합니다.

Summary

PermGen space situation

  • memory space는 완벽하게 제거됩니다.
  • PermSize와 MaxPermSize JVM argument는 무시되며, 시작될때 경고를 표시합니다.

Metaspace memory allocation model

  • class의 metadata는 거의 대부분 native memory에 저장됩니다.
  • class의 metadata를 사용하기 위한 klasses들은 모두 제거됩니다.

Metaspace capacity

  • 기본적으로 metaspace는 native memory를 사용하기 때문에, OS에서 사용 가능한 memory 영역 모두를 사용 가능합니다.
  • 새로운 Flag(MaxMetaSpaceSize)가 가능합니다. 이는 class metadata를 저장하기 위한 최대한의 memory size를 정하는 것이 가능합니다. 만약에 Flag를 설정하지 않는다면, Metaspace는 application의 동작에 따라 가변적으로 동작하게 됩니다.

Metaspace garbage collection

  • dead class와 classloader의 GC는 MaxMetaspaceSize에 도달하면 발생합니다.
  • Metaspace의 tuning과 monitoring은 GC의 횟수와 지역을 제한하기 위해 필요한 작업입니다. 과도한 Metaspace GC는 classloader의 memory leak 또는 적합하지 않은 Application의 memory size를 초래합니다.

Java heap space impact

  • 여러 다양한 데이터들은 Java Heap space로 저장 영역이 이동되었습니다. 결국 기존 JDK7에서 JDK8로 업그레이드를 하는 경우, Java Heap memory를 증가시킬 필요가 있습니다.

Metaspace monitoring

  • metaspace 사용량은 GC log output을 통해서 확인 가능합니다.
  • Jstat * JVirtualVM 은 아직 metaspace를 monitoring 하지 못합니다. 아직 예전 PermGen space reference를 확인하도록 되어 있습니다.

PremGen vs. Metaspace runtime comparison

새로운 Metaspace memory space의 동작을 이해하기 위해서, 우리는 metadata leaking java program을 준비했습니다.

주어진 시나리오에 따라 다음과 같이 테스트를 진행했습니다.

  • JDK 1.7에서 PermGen memory space를 128M로 설정 후, PermGen memory의 감소를 관찰합니다
  • JDK 1.8에서 Metaspace memory space의 GC와 dynamic increase를 monitoring 합니다.
  • JDK 1.8에서 MaxMetaspaceSize를 128M로 설정 후, Memory의 감소를 관찰합니다.

JDK 17 - PermGen depletion

  • Java program with 50K configured iterations
  • Java heap space는 1024 MB
  • Java PermGen space 는 128MB

JVirtualVM의 경우, PermGen depletion은 약 30K+개의 class가 class loader에 로딩되었을 때, 발생합니다. GC output을 통해 다음 log를 확인할 수 있습니다.

Class metadata leak simulator
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
ERROR: java.lang.OutOfMemoryError: PermGen space

JDK 1.8 - Metaspace dynamic re-size

  • Java program with 50K configured iterations
  • Java heap space는 1024 MB
  • Java metaspace space : 지정하지 않음 (default)


GC output에서 볼 수 있듯이, JVM Metaspace는 20MB에서 320MB로 dynamic resizing이 이루어진 것을 볼 수 있습니다. 또한 JVM의 GC 시도를 GC output을 통해서 확인 할 수 있습니다. 우리는 memory leak이 발생하는 application을 구성하고 있기 때문에, JVM은 dynamic expand 밖에 할 수 없습니다.

이 프로그램은 50K 정도의 OOM event와 50K+ 정도의 classes들을 load 시킬 수 있습니다.

JDK 1.8 - Metaspace depletion

  • Java program with 50K configured iterations
  • Java heap space는 1024 MB
  • Java metaspace space : 128M (-XX : MaxMetasapceSize=128M)

JVirtualVM에서 보듯이, metaspace 감소는 약 30K+ 개의 class들이 감소한 후 부터 발생하고 있습니다. 마치 JDK 1.7과 동작이 비슷합니다. 이러한 현상을 GC output을 통해서 확인할 수 있습니다. 또다른 흥미로운 현상은 native memory footprint를 보면 알 수 있듯이, native memory는 MaxMetaspaceSize의 2배를 할당하고 있다는 점입니다. 이것은 native memory 낭비를 줄일, Metaspace의 재할당 정책에 대한 좋은 tunning point입니다.

이제 java program output을 통해 Exception을 확인해보도록 하겠습니다.

Class metadata leak simulator
Author: Pierre-Hugues Charbonneau
http://javaeesupportpatterns.blogspot.com
ERROR: java.lang.OutOfMemoryError: Metadata space
Done!

예상과 같이, Metaspace가 128MB가 되었을 때, 마치 JDK 1.7과 거의 유사한 base line을 갖는 50 K 정도의 객체를 생성할 때 Exception이 발생합니다. 새로운 OOM(Out Of Memory) error는 JVM에 의해서 발생되게 됩니다. OOM event는 memory allocation failuire에 의해 발생되게 됩니다.

metaspace.cpp 

Final words

새로운 Java 8 Metaspace에 대해서, 빠른 분석과 설명을 알아보길 바랍니다. 현 분석대로라면 마지막 실험에서 보셨던 것과 같이, Metaspace GC 또는 OOM 조건이 발생하는 것에 대한 monitoring과 tuning이 필요한 것을 보여줍니다. 다음 article에서는 새로운 기능에 연관된 performance 향샹에 대한 비교를 포함할 수 있었으면 좋겠습니다.

Posted by Y2K
,