1. 서론
자바 공식문서 링크: https://openjdk.org/jeps/122
Perm Gen이 자바 8부터 Metaspace영역으로 변경 되어 Native 영역으로 옮겨 졌다는 부분을 공부하는데 static 영역에 관련되서는 GC로 관리된다 또는 Native 영역이라 아니다등 명확한 정답을 얻기 어려웠습니다. 이에 개인적으로 좀 더 조사를 하게 되었고 잊지 않기 위해 기록을 해 보기로 하였습니다.
2. 자바 런타임 메모리 영역
A. 스레드관련 메모리
: 스레드 영역은 스레드의 시작과 종료를 같이 함으로 메소드나 스레드 호출과 함께 생성 되며 스레드 종료 시 사라집니다.
- Java Stack (자바 스택 프레임) : 지역변수, 매개변수, 메소드 호출정보 (함수 정보), 반환 주소등.
- PC Registers : 스레드의 명령어 주소를 가진다.
- Native Method Stacks: 자바 언어가 아닌 시스템 콜을 하기위해 C언어 등으로 이루어진 네이티브 메소드를 호출하기 위한 스택.
B. 공유 메모리
- Heap : 객체, 인스턴스(primitive변수도 인스턴스 변수는 객체와 함께 힙에 저장), 배열 저장. JVM이 관리.
- Method Area: JVM에서 클래스 로딩때 읽은 런타임 상수 풀, 메서드와 필드, Static 변수, 메서드 바이트 코드등 보관. (Perm Gen -> Metaspace)
3. Perm Gen이 메타스페이스로 변경
Java 8 이전에 메서드 영역은 Perm Gen 영역으로 GC도 일어나지 않으며 메모리도 지정 후 변경이 어려워 Out of Memory에러가 생기기 쉬웠습니다. 그래서 Perm Gen 영역의 클래스의 메타 정보(meta-data)는 Native Memory로 interned String 과 Class Statics는 heap의 영역으로 변경 되었다고 합니다. (JEP 122: The proposed implementation will allocate class meta-data in native memory and move interned Strings and class statics to the Java heap. )
즉, 상수 풀과 클래스 메타 정보는 Native 영역으로 옮겨져서 meta space로 불리며 스레드 관련 메모리들 처럼 OS에 의해 관리 되기에 필요시 메모리를 더 가져 올수 있어 Out of Memory 에러가 생기지 않습니다.
그리고 interned String들과 static정보들은 heap으로 옮겨져 JVM의 관리를 받으며 GC의 영향을 받게 되는데 이때 헷갈리는게 static 객체, 메소드, 변수의 위치가 달라서 입니다.
Static 메소드의 경우 클래스의 메타 정보이기에 Meta Space에 들어가게 되며 OS에 의해 관리 됩니다. Static 변수와 클래스는 heap으로 옮겨져서 GC의 영향권안에 들어가게 됩니다. (where static is stored in java8 and above version?).
추가적 정보이지만
MetaSpace도 GC가 되는 경우(오늘부터 개발자님)도 있고 Static Object의 경우 참조가 되지 않는 경우나 클래스 로더에 의해 언로드 된경우 GC 되는데 GC가 되는 조건이 까다로운 듯하다(박종훈님). Static 영역의 저장영역에 관한 포스트이기에 이 부분은 좀더 공부를 해보려고 한다.
참고
where are static methods and static variables stored in java?
where static is stored in java8 and above version?