개요
Java 8은 2014년 3월에 출시되었으며, Java 7과 다른 가비지 컬렉터 구조를 가집니다. 대표적으로 Java 7의 PermGen이 Java 8에서 Metaspace로 대체되었습니다. 어떤 차이가 있는지 알아보겠습니다.
PermGen
PermGen(Permanent Generation)은 클래스와 메서드 메타 데이터, static 내용들이 저장되는 힙에서 분리된 별도의 힙 공간입니다. 또한 바이트코드, 이름, JIT 정보를 저장합니다. 기본 최대 메모리 크기는 32bit에서 64MB, 64bit에서 82MB입니다.
JVM의 메모리 크기를 다음 명령어로 설정할 수 있습니다.
- -XX:PermSize=[size] is the initial or minimum size of the PermGen space
- -XX:MaxPermSize=[size] is the maximum size
하지만 Java 8부터는 PermGen 공간을 삭제했기 때문에 PermGen 관련 명령어를 사용하면 아래와 같은 경고가 나옵니다.
>> java -XX:PermSize=100m -XX:MaxPermSize=200m -version
OpenJDK 64-Bit Server VM warning: Ignoring option PermSize; support was removed in 8.0
OpenJDK 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
...
PermGen은 제한된 메모리 크기 때문에 OutOfMemoryError를 발생시킵니다. 클래스 로더는 제대로 가비지를 수집하지 못해서 메모리 누수로 이어지는 경우가 많습니다. 그러므로, 새로운 클래스 로더를 개발할 때 에러가 자주 발생합니다.
OutOfMemoryError는 java.util.lang.VirtualMachineError의 하위 클래스입니다. JVM이 가비지 컬렉션 수행을 너무 오래 하고 힙 공간을 거의 회수하지 못할 때 발생합니다. Java docs에 따르면, 기본적으로 JVM은 98% 이상 시간을 가비지 컬렉터 작동에 소비하고 그 결과 힙 공간의 2% 미만이 회수되면 OutOfMemoryError가 발생합니다. 가비지 컬렉터는 메모리 초기화에 너무 많은 시간을 소비했고 반복적으로 회수에 실패했기 때문입니다. 애플리케이션이 거의 모든 메모리를 사용했다는 뜻입니다. CPU가 가비지 컬렉터 작업에 대부분 사용되기 때문에 수 밀리초 안에 끝날 작업들이 훨씬 오래 걸립니다.
Metaspace
Metaspace는 Java 8 버전에 새롭게 등장한 메모리 공간입니다. 힙 영역의 PermGen 메모리 공간이 없어지고 native memory 영역에 Metaspace가 새로 추가되었습니다. 기존에 PermGen에서 관리했던 static 변수와 상수는 힙 영역으로 이동하였고 native memory 영역은 OS가 관리합니다.
다음 설정이 추가되었습니다.
MetaspaceSize, MaxMetaspaceSize - Metaspace의 사이즈를 설정할 수 있습니다.
MinMetaspaceFreeRatio - 가비지 컬렉터 초기화 후 사용 가능한 클래스 메타 데이터 용량의 최소 백분율
MaxMetaspaceFreeRatio - 여유 공간의 감소를 막기 위해 가비지 컬렉터 초기화 후 클래스 메타 데이터 용량의 최대 백분율
native memory 영역은 자동으로 커지며, 클래스 메타 데이터 사용량이 최대 metaspace 사이즈에 도달하면 가비지 컬렉터는 자동으로 사용 종료된 클래스를 초기화합니다.(기본 metaspace 사이즈는 64bit 기준으로 프로세서가 취급할 수 있는 메모리 상한에 가깝습니다.) 따라서 OutOfMemoryError 문제를 거의 해결했습니다.
그렇다고 항상 Metaspace가 안전한 것은 아닙니다. 과도한 클래스 로드로 전체 사이즈가 커지고 native memory 여유가 부족해질 수 있습니다. 따라서, OS의 프로세스 사이즈를 모니터링해야 합니다.
참고
https://johngrib.github.io/wiki/java8-why-permgen-removed/
https://karunsubramanian.com/websphere/one-important-change-in-memory-management-in-java-8/
'학습 > Java' 카테고리의 다른 글
Java 8에 등장한 Optional이란? (0) | 2022.10.29 |
---|---|
자바 8에 추가된 Date Time API (0) | 2022.10.28 |
jar war 차이점 (0) | 2022.04.26 |
자바 비동기 (0) | 2021.08.16 |
RestTemplate (0) | 2021.08.15 |