들어가며

JVM 공부 도중 레퍼런스 마다 Method Area와 Permanent Generation 용어가 각각 나타나거나 나타나지 않는 곳도 있어서, JVM의 물리적인 구조의 이해가 약간 어려웠다. 그리고, Permanent Generation 이 Heap 으로 표기된 경우, 아닌 경우도 레퍼런스마다 다 달라서 혼란스러웠다. Metaspace 용어 또한 등장하는데, 레퍼런스마다 있는 곳도 있고, 없는 곳도 있었다. 이 부분은 자바 버전에 따라서 JVM 스펙이 바뀐 부분이었다. 이 부분들에 초점을 맞추어, 자바 버전에 따라서 바뀐 부분을 찾아 정리해 보았고, 앞에 기술했던 용어상 혼란스러웠던 부분도 찾아서 정리해 보았다.


Java 7

  • Permanent Generation
    • Class의 메타 데이터 (바이트코드 포함)
    • Method의 메타 데이터
    • static 객체, 상수 (static final)
    • 상수화된 String Object
    • Class와 관련된 배열 객체 메타데이터
    • JVM 내부 객체들과 JIT 최적화 정보
  • 문제점 - 메모리 관리의 불편함
    • String Constant Pool, static object, Class 메타 데이터들이 쌓여 java.lang.OutOfMemory에러 발생
      • Permanent Generation은 고정된 메모리 사이즈. MAX 값 설정되어 있으며, 초과 에러
  • Permanent Generation은 Non-Heap Memory
    • 국내에 Heap으로 표현된 그림은 Generation 관점에서 JVM 메모리 개념을 설명하기 위한 것일 뿐, Heap이 아님
  • 오라클 HotSpot JVM 에서는 Method AreaPermanent Generation라고 부른다.

Java 8

  • Permanent Generation 제거하고, Metaspace 추가해 Native Memory 영역으로 이동
  • 변경 사항
    • Class의 메타 데이터 (바이트코드 포함) → Metaspace 이동
    • Method의 메타 데이터 → Metaspace 이동
    • static 객체, 상수 (static final) → Heap 이동
    • 상수화된 String Object → Heap 이동
    • Class와 관련된 배열 객체 메타데이터 → Metaspace 이동
    • JVM 내부 객체들과 JIT 최적화 정보 → Metaspace 이동
    • ⇒ static object, literal string 가 Heap으로 이동하여, GC의 대상이 됨
  • Heap은 JVM에 의해 관리, Native Memory는 OS에 의해 관리됨
  • Metaspace 개선점
    • Native Memory에 속하여 OS에 의해 관리되므로, 개발자는 메모리 신경 쓸 필요 없다.
    • MAX 값 설정하지 않으면 디폴트로 OS가 제공할 수 있는 만큼 자동으로 늘어남.
    • MAX 값을 설정하지 않으면 디폴트 값으로 64비트 Integer의 최댓값인 18446744073709547520으로 설정됨
    • 대신, Native Memory를 사용하므로 동일한 서버에 다른 Application까지 모두 죽는 현상 (전체 서버 다운) 이 생길 수 있다.
      • Heap Size모니터링 뿐만 아니라, Metaspace 모니터링이 필요할 수 있음
    • 그래서 Metaspace의 크기를 제한하는 -XX:MetaspaceSize, -XX:MaxMetaspaceSize 옵션을 제공한다.
    • GC 기능을 가지고 있어서 더 이상 사용하지 않는 클래스 메타데이터들을 제거함으로써 메모리를 효율적으로 사용한다.

Metaspace

  • Permanent Generation to Metaspace
    • Java 8부터 Permanent Generation이 Metaspace로 대체
    • Native Memory 영역에 저장
  • 클래스 로더가 로드한 클래스의 메타 데이터 metadata가 저장되는 공간
  • 할당(생성) allocate 시점
    • 클래스가 로드될 때, metaspace가 클래스 로더에 의해 할당됨
  • 해제 release 시점
    • 클래스의 live instance 없고, 참조도 없을 때, GC 후에 해제됨
  • GC
    • Heap 입장에서는 GC를 통해 얻을 수 있는 것이 많지 않더라도, metaspace 내 오래된 class metadata 제거를 위한 GC가 수행되는 것이 효율적일 수 있다.
    • metaspace에서 유도되는 GC 종류
      • metaspace 할당 시
        • 지속적으로 metadata 를 쌓으면서 확장하지만, 공간의 효율적인 활용을 위해 어느 임계 지점에서는 오래된 class loader들을 GC로 정리한다.
      • metaspace OOM 시
        • 메모리 용량이 MaxMetaspaceSize를 초과하거나, Compressed Class Space 가 부족할 때 GC가 발생할 수 있다.

출처

https://jaehoney.tistory.com/177
https://obv-cloud.com/41
https://becomeweasel.tistory.com/entry/JVM%EC%9D%98-Java-8%EC%97%90%EC%84%9C%EC%9D%98-%EB%B3%80%ED%99%94
https://blog.voidmainvoid.net/184
https://stackoverflow.com/questions/41358895/permgen-is-part-of-heap-or-not
https://blog.naver.com/simjunbo/221080829920
https://d2.naver.com/helloworld/1230
https://jaemunbro.medium.com/java-metaspace%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-ac363816d35e

+ Recent posts