목차

Java 8 이후 변화

Java 8 전에는 JVM의 힙 메모리는 크게 Young Generation, Old Generation, Permanent Generation으로 나뉘었다. 하지만 Java 8 이후 부터 Permanent Generation은 없어졌고, 이를 대체하는 Metaspace 가 사용된다.

PermGen

image
JVM Heap 메모리 구조(~ Java 7), Wikipedia

PermGen은 메인 힙으로부터 분리된 특수한 힙 공간이다. PermGen에는 Symbol, Interned String, 로드된 클래스 메타데이터, static 변수 및 메서드, static 오브젝트에 대한 참조 등을 저장한다. Method Area라고도 불린다.

PermGen이 저장하는 데이터는 Java 7에서 변경되었다. Symbol은 Native memory에 저장되고, Interned StringClass static은 Java Heap에 저장되도록 변경되었다.

PermGen의 크기를 조절할 수 있는 JVM 옵션은 아래와 같다.

  • -XX:PermSize=size: 최소 및 초기 크기를 지정한다.
  • -XX:MaxPermSize=size: 최대 크기를 지정한다.

PermGen은 Java8 부터 완전히 제거되었기 때문에, Java8 이후부터는 위 명령이 모두 무시된다.

Metaspace

image
JVM Heap 메모리 구조(Java 8 ~), 출처: https://help.sap.com

Java8 부터 등장한 메모리 공간으로, 힙이 아닌 Native Memory 에 속한다. Native Memroy는 Java Heap이 아니기 때문에, 운영체제로부터 메모리를 할당받고, 그 크기가 자동으로 증가하도록 설정되어 있다.

Java7 에서 이전에 PermGen이 담당하던 Symbol, Interned String, Class static을 모두 다른 공간으로 이전하였다. 따라서 Metaspace는 오직 로드된 클래스 메타데이터만을 저장하는 공간을 말한다.

이 Metaspace의 크기를 지정할 수 있는 옵션은 아래와 같다.

  • -XX:MaxMetaspaceSize=size: Metaspace의 최대 크기를 지정한다. 기본값은 없다. 즉, Metaspace의 크기는 계속해서 증가할 수 있다.
  • -XX:MetaspaceSize=size: Metaspace의 크기가 지정된 값을 넘어가면 full GC를 실행하여 불필요한 class를 unload 하도록 설정한다. 이 값에 도달하여 full GC가 실행된 뒤에는 GC가 이 값을 관리한다. 기본값은 플랫폼에 따라 상이하다.

위의 명령어를 통해, GC는 Java Heap만 관리하는 것이 아니라, Native Memory인 Metaspace도 관리한다는 것을 알 수 있다. (full GC를 통해 불필요한 클래스 메타데이터를 unload 한다.)

Native Memory

JVM의 Native Memory, 즉, 힙을 제외한 메모리에는 Compressed class space, Thread, Code cache, GC, Symbol, Internal이 포함된다.

  • Compressed class space: 로드된 클래스 파일들의 정보를 갖는다. (Metaspace)
  • Thread: JVM 내의 thread들이 사용하는 메모리를 말한다.
  • Code cache: JIT가 자신의 결과물을 저장하기 위해 사용하는 공간이다.
  • GC: GC가 사용하는 정보를 담기 위한 공간이다.
  • Symbol: field 이름, 메서드 signature와 같은 symbol들을 저장하는 공간이다.
  • Internal: 위의 어떤 공간에도 해당하지 않는 데이터가 차지하는 공간을 말한다.

참고자료