일단 자바에서 위 키워드의 기능이 아닌 메모리 관점에서 정리해보자고 한다.
static int x = 3;
static final int y = 5;
위 둘의 차이점이 뭘까?
대표적인 차이점은 final 키워드 유무 차이이다. 그럼 final 유무 차이는 뭘까?
final 키워드가 붙지 않은 x는 값을 수정할 수 있고, final 키워드가 붙은 y는 값을 재할당 불가능하다.
위에 정보는 자바 공부를 했다면 금방 알 수 있을 것이다.
하지만 메모리 관점에서 봐보자. 둘은 어떻게 저장될까?
먼저 Java의 컴파일 과정 간단하게 알아보자
- Java 컴파일러를 통해 .java 파일을 .class 파일로 변환한다.
- 해당 class 를 참조할 때 클래스로더를 통해 JVM의 메모리에 로딩한다. (class 정보를 JVM의 runtime constant pool에 저장한다.)
- 클래스의 constant pool 내의 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경하고, static 변수들을 적절한 값으로 초기화한다.
- 실행 엔진을 통해 바이트 코드를 명령어 단위로 실행한다.
- 심볼릭 레퍼런스 : 참조하는 클래스의 특정 주소가 아닌 참조하는 대상의 이름으로 참조하는 것
- 다이렉트 레퍼런스 : 참조하는 클래스의 특정 메모리 주소를 참조하는 것
이제 메모리 관점으로 봐보자
static 키워드가 붙든, 아니든 각 클래스 파일의 constant pool에는 클래스에 관한 모든 정보가 저장된다.
즉, 위에서 말한 static , static final도 constant pool에 저장되어 있다.
컴파일을 완료해 관련 정보들을 Runtime Constant Pool에 올렸다고 하면 다음과 같다.
static 변수는 값을 변경할 수 있는 상태이지만, 해당 클래스의 모든 인스턴스가 공유하는 변수이다. 메서드 영역의 class variable 라는 공간에 저장된다.
static final int c도 큰 범주로 static 변수에 속하므로, static 변수와 똑같이 저장된다. 대신 static final 이 붙으면 상수이므로, Runtime Constant Pool 내부의 상수를 저장하는 공간에도 따로 저장이 된다.
즉, 정리하면 static object 들은 변수와 레퍼런스 모두 메서드 영역에 저장된다.
위 내용은 자바 8 버전 이전 내용이다.
자바 8버전 이후는 PermGen 영역이 MetaSpace영역으로 바뀌면서, static object의 OOM 문제를 해결하기 위해, 레퍼런스는 MetaSpace 영역에서 그대로 관리하나, 실제 저장되는 공간은 Heap 영역에 저장된다.
final vs static final
- 메서드 내의 지역변수로 선언된 final은 해당 메서드 스택 프레임에 저장될 수 있습니다. 메서드 종료 후 스택 프레임이 제거되면서 해당 변수도 저장됩니다.
- 인스턴스 변수로서 final은 해당 인스턴스가 생성될 때 메모리에 할당됩니다. 각 인스턴스의 상태를 나타내는 데이터이므로, 인스턴스의 메모리 공간에 저장됩니다.
- static final은 클래스 내에서 공유되는 것이므로, 클래스가 로딩될 때 메모리에 할당되며, 메서드 영역에 저장되어 있습니다.
정리
- static 이 붙은 것들은 모두 메서드 영역에 저장되어 있다.
- static final은 상수로 취급되며, Runtime Constant Pool 내의 상수가 저장되는 공간에도 저장이 된다.
- final만 붙으면 지역변수나, 인스턴스의 변수의 역할을 할 수 있으므로, 해당 메서드나, 인스턴스가 생성될 때 메모리에 할당되고 해제된다.
- 자바 8버전 이후에 PermGen 영역이 MetaSapce 영역으로 바뀌면서, 메서드 영역에서 static object의 레퍼런스만 관리하고, 실제로 저장되어 있는 공간은 힙에 저장하도록 변경되었다.
'Back-end' 카테고리의 다른 글
Primitive Type vs Wrapper Class + Wrapper Class 동일성 비교 (0) | 2023.08.16 |
---|---|
동일성 vs 동등성 (0) | 2023.08.16 |
2023.08.13 TIL (0) | 2023.08.13 |
왜 enum(열거형)을 상속하지 못할까? (0) | 2023.08.13 |
자바 static (0) | 2023.08.13 |