들어가며
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 값 설정되어 있으며, 초과 에러
- String Constant Pool, static object, Class 메타 데이터들이 쌓여
- Permanent Generation은 Non-Heap Memory
- 국내에 Heap으로 표현된 그림은 Generation 관점에서 JVM 메모리 개념을 설명하기 위한 것일 뿐, Heap이 아님
- 오라클 HotSpot JVM 에서는
Method Area
를Permanent 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가 발생할 수 있다.
- 메모리 용량이
- metaspace 할당 시
출처
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