백엔드

[java] 변수의 유효 범위와 메모리

음그냥 2025. 3. 2. 05:43
728x90
반응형

 

  • 변수의 유효 범위와 메모리
  • 변수의 유효 범위(scope)와 생성과 소멸(life cycle)은 각 변수의 종류마다 다름
  • 지역변수, 멤버 변수, 클래스 변수는 유효범위와 life cycle, 사용하는 메모리도 다름

 

  • static 변수는 프로그램이 메모리에 있는 동안 계속 그 영역을 차지하므로 너무 큰 메모리를 할당하는 것은 좋지 않음 (큰배열같은건  절대X)
  • 클래스 내부의 여러 메서드에서 사용하는 변수는 멤버 변수로 선언하는 것이 좋음
  • 멤버 변수가 너무 많으면 인스턴스 생성 시 쓸데없는 메모리가 할당됨
  • 상황에 적절하게 변수를 사용해야 함

Java 메모리 구조 (낮은 주소 → 높은 주소)

┌────────────────────────── 높은 주소 (High Address)
│  📌 커널(Kernel) 영역  (운영체제 관리)
├──────────────────────────
│  📌 스택(Stack) 영역   (메서드 호출 시 지역 변수 저장)
│      ├── 메서드3()
│      ├── 메서드2()
│      ├── 메인 메서드()
│      └── (LIFO 구조, 함수 호출 시 증가)
├──────────────────────────
│  📌 힙(Heap) 영역   (new로 생성한 객체 저장)
│      ├── 객체1
│      ├── 객체2
│      ├── 객체3
│      └── (GC에 의해 정리됨)
├──────────────────────────
│  📌 메서드(Method) 영역
│      ├── 클래스 정보
│      ├── 메서드 바이트코드
│      ├── Static 변수
│      ├── 🟢 **상수 풀(Constant Pool)** 
│          ├── "Hello" (문자열 리터럴)
│          ├── final 상수
│          ├── 클래스 메서드 정보
│      └── (클래스 로딩 시 생성)
├──────────────────────────
│  📌 .bss (초기화되지 않은 전역 변수)
│  📌 .data (초기화된 전역 변수)
├──────────────────────────
│  📌 코드(Code) 영역
│      ├── 바이트코드 (JVM 실행 코드)
│      ├── JIT 컴파일된 네이티브 코드
└────────────────────────── 낮은 주소 (Low Address)

 

728x90

📌 메모리 구조에서의 final 상수

  1. 상수풀(Constant Pool):
    • final 상수로 선언된 값 (예: "Hello")은 상수풀에 저장.
    • 상수풀은 문자열 리터럴이나 final 상수 값을 공유하고, 중복을 피하기 위해 메모리에서 하나만 존재.
  2. 메서드(Method) 영역:
    • static final 변수메서드 영역에 저장.
    • 이 변수는 클래스 로딩 시 메모리에 한 번만 할당되고, 모든 객체에서 공유.
    • final 변수라도 객체 변수라면 각 객체마다 힙에 저장되지만, 값은 변경되지 않음.

 

public class Example {
	
    static final String S1 = "World"; // ✅ "World"는 상수풀에 저장됨
    final String S1 = "World"; // ✅ "World"는 상수풀에 저장됨

    public static void main(String[] args) {
        String str1 = "Hello"; // ✅ 상수풀에 저장됨
        String str2 = "Hello"; // ✅ 기존 "Hello"를 재사용 (같은 객체)
        String str3 = new String("Hello"); // ✅ 힙(Heap)에 새로운 객체 생성

        System.out.println(str1 == str2); // true (같은 객체)
        System.out.println(str1 == str3); // false (다른 객체)
    }
}

 

  • S1는 메서드영역에 저장되고, 문자열 리터럴인 "World"는 상수풀에 저장되고, S2와 공유
  • S2는 힙메모리영역에 저장되고, 문자열 리터럴인 "World"는 상수풀에 저장되고, S1와 공유
  • str1과 str2는 스택메모리에 생성되고, 같은 문자열 리터럴을 사용하므로 상수풀에서 공유됨
    str3은 new String("Hello")로 생성되었기 때문에 Heap 영역에 별도로 저장됨
728x90
반응형