본문 바로가기
Back-end

static vs static final vs final In Java

by 신재권 2023. 8. 15.

일단 자바에서 위 키워드의 기능이 아닌 메모리 관점에서 정리해보자고 한다.

static int x = 3;
static final int y = 5;

위 둘의 차이점이 뭘까?

대표적인 차이점은 final 키워드 유무 차이이다. 그럼 final 유무 차이는 뭘까?

final 키워드가 붙지 않은 x는 값을 수정할 수 있고, final 키워드가 붙은 y는 값을 재할당 불가능하다.

위에 정보는 자바 공부를 했다면 금방 알 수 있을 것이다.

 

하지만 메모리 관점에서 봐보자. 둘은 어떻게 저장될까?

 

먼저 Java의 컴파일 과정 간단하게 알아보자

  1. Java 컴파일러를 통해 .java 파일을 .class 파일로 변환한다.
  2. 해당 class 를 참조할 때 클래스로더를 통해 JVM의 메모리에 로딩한다. (class 정보를 JVM의 runtime constant pool에 저장한다.)
  3. 클래스의 constant pool 내의 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경하고, static 변수들을 적절한 값으로 초기화한다.
  4. 실행 엔진을 통해 바이트 코드를 명령어 단위로 실행한다.
  • 심볼릭 레퍼런스 : 참조하는 클래스의 특정 주소가 아닌 참조하는 대상의 이름으로 참조하는 것
  • 다이렉트 레퍼런스 : 참조하는 클래스의 특정 메모리 주소를 참조하는 것

 

이제 메모리 관점으로 봐보자

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