모종닷컴

Compressed Class 영역 본문

Programming/JAVA

Compressed Class 영역

모종 2025. 10. 19. 22:10
반응형

Docker Container에 리소스 제한 설정을 CPU(1.0), Memory(1GB)로 설정한 후 JVM 메트릭을 확인하는데 Non-heap 영역이 1GB가 넘게 할당되있는 것을 봤습니다.

메모리는 일단 아래와 같이 할당되었습니다.

  • JVM Heap : 248MiB
  • JVM Non-Heap : 1.23GiB

혹시 컨테이너 메모리 제한을 잘못설정한건지 리눅스 cgroup을 봤지만 리소스 제한은 잘 된것으로 보였습니다.

컨테이너 메모리는 1GB로 설정했는데 어떻게 된 일 일까요??

Compressed Class 영역

JVM Non-Heap을 들여다 보니 metaspace가 -1B, Compressed Class: 1GiB가 할당되었고, 나머지 240MiB는 기타 다른 영역에 할당됬습니다.
결국 이 Compressed Class라는 영역이 엄청크게 할당되있었습니다.

Compressed Class 영역에 대하여 알아봐야겠습니다.

  • UseCompressedOops + UseCompressedClassPointers 활성화시 클래스 메타데이터를 위해 네이티브 메모리 상에서 논리적으로 두 개의 다른 영역이 사용됩니다.
  • 일반적인 메타데이터는 Metaspace 영역, 클래스 참조용 포인터는 Compressed Class 영역에 저장되게 됩니다.
  • CompressedClassPointer는 64비트 프로세스 환경에서 클래스 포인터를 표현할 때 32비트 오프셋을 사용하여 표현됩니다.
  • CompressedClass 영역의 사이즈 디폴트값은 1GB (-XX:CompressedClassSpaceSize)로 설정되어 있습니다.
  • 클래스 포인터를 위한 공간은 최초 예약 공간이며 필요에 따라 커밋됩니다.

정리하자면 Compressed Class 영역은 클래스 포인터가 저장되는 영역이고, 디폴트가 1GB로 설정되있다는 것을 알 수 있었습니다.

추가 의문: Compressed Class Pointer 방식이 왜 필요한가?

64비트 컴퓨터의 주소 참조를 위해 64비트 포인터를 사용할 수 있습니다. 하지만 대부분 애플리케이션은 64비트 주소 공간 전체를 다 쓰는 경우는 없기 때문에 64비트를 낭비하지 않고, 더 작은 32비트 포인터로 대체하기 위함인것으로 보입니다.

추가 의문: OS는 왜 1GB 넘는 공간을 요구하는 애플리케이션을 실행시켜준걸까?

Compressed Class 영역은 해당 공간을 예약만 하는 가상 주소이지 실제 물리 메모리를 즉시 할당(commit)하지 않기 때문에 실행시켜준게 아닐까 싶습니다.

즉 JVM 메트릭에서 1.23 GiB가 할당된 상태로 애플리케이션이 올라간것처럼 보이지만 실제 메모리에 할당된 상태는 아니라고 볼 수 있을 것 같습니다.

반응형