[JAVA] JAVA 메모리 모델과 변수의 종류 : static, 지역변수, 레퍼런스 변수 이해하기

static, 지역변수, 레퍼런스 변수 등 JAVA의 변수의 종류와 메모리 모델에 대해 알아본다.


static 변수

  • 인스턴스가 아닌 클래스에 귀속
  • 인스턴스가 여러 개 생성되도 static 변수는 딱 하나
    • 클래스가 메모리에 로드될 때 한 번 생성됨
    • 객체가 아닌 클래스 자체에 저장되기 때문에 모든 객체가 동일한 메모리 위치를 공유함
  • 특징

    • 수명
      • 클래스가 메모리에 로드될 때 생성되고, 프로그램이 종료될 때까지 유지됨
      • 일반적인 지역변수와 달리 블록을 벗어나도 소멸되지 않음
    • 메모리 위치
      • static 변수는 Method Area에 저장됨
    • static 변수의 객체 독립성

      • static 변수가 클래스 자체에 속해 있기 때문에, 객체를 생성하지 않아도 해당 클래스 이름만으로 직접 접근 가능
      • 예시

        •   public class Example {
                static int staticVar = 10; //static 변수 (클래스 변수)
                int instanceVar = 20; //인스턴스 변수 (객체 변수)
          
                public static void main(String[] args) {
                    //static 변수는 클래스 이름으로 접근 가능
                    System.out.println("Static Variable: " + Example.staticVar); //출력: 10
          
                    //객체를 생성하지 않아도 static 변수에 접근 가능
                    Example.staticVar = 30;
                    System.out.println("Static Variable: " +Example.staticVar); //출력: 30
          
                    //객체를 생성해야 인스턴스 변수에 접근 가능
                    Example obj1 = new Example();
                    System.out.println("Instance Variable: " + obj1.instanceVar); //출력: 20
                }
            }
          
  • static 변수 사용 시점

    • 공유 데이터가 필요할 때
      • 모든 객체에서 동일한 값 공유해아 할 때 사용
      • 예: 총 객체 갯수, 공통 설정값 등
    • 객체와 무관하게 동작해야할 때
      • 클래스 자체의 정보를 나타내거나, 객체 없이 사용 가능한 값을 저장할 때
      • 예: 수학 상수 Math.PI, System.out.println()의 out도 static
  •   public class TestClass{
          static int number;
      }
    
      public class Test{
          public static void main(String []arg){
              TestClass class1 = new TestClass();
              TestClass class2 = new TestClass();
    
              class1.number = 3;
              class2.number = 5;
    
              System.out.println("class1의 number: " + class1.number);
              System.out.println("class2의 number: " + class2.number);
          }
      }
      // class1의 number: 5
      // class2의 number: 5
    
  • 마지막에 number에 5가 저장되어있기 때문에 5가 두번 출력

Method Area

  • JVM(Java Virtual Machine)의 메모리 구조 중 하나
  • 클래스 수준의 정보를 저장하는 영역
    • 저장되는 데이터 종류
      1. 클래스 정보
        • 클래스의 이름, 부모 클래스, 접근 제어자 등의 메타데이터
      2. 클래스 변수 (static 변수)
        • 클래스가 로드될 때 메모리에 할당되며 모든 객체에서 공유됨
      3. 메서드 정보
        • 메서드의 이름, 리턴 타입, 매개변수 타입 등
        • 메서드의 바이트코드 포함
      4. 상수 (Constant Pool)
        • 컴파일 시 생성된 상수(문자열, 숫자 리터럴 등)와 참조(메서드 참조, 클래스 참조)가 저장됨
      5. 런타임 상수 풀(Runtime Constant Pool)
        • 런타임 중에 동적으로 생성된 상수와 참조.
  • 특징
    • JVM내에서 유일 : 모든 스레드가 공유
    • 수명 : JVM이 종료될 때까지 유지
    • Garbage Collection 대상 아님 : 클래스 정보는 명시적으로 제거되지 않음

지역변수 & 레퍼런스 변수

지역변수 (Local Variable)

  • 특정 블록이나 함수 안에서만 선언되고 사용가능한 변수
  • 해당 블록이나 함수가 실행을 마치면 메모리에서 삭제되며, 외부에서 접근 불가능
  • 특징
    • 유효 범위 (Scope)
      • 변수가 선언된 블록(중괄호 {}로 감싸진 영역) 내에서만 유효
    • 초기화 필요
      • 지역변수는 자동으로 초기화 되지 않음
    • 메모리 관리
      • 지역변수는 함수 호출시 생성되고, 함수 종료 시 자동으로 소멸됨
      • 일반적으로 스택 메모리 사용
  • 예제
    •   public class Example {
            public static void main(String[] args) {
                int x = 1; // x는 main 메서드의 지역 변수
                if (x < 10) {
                    int y = 20; // y는 if 블록의 지역 변수
                }
                //y는 if블록 밖에서 사용할 수 없음
                }
        }
      

레퍼런스 변수 (Reference Variable)

  • 객체의 메모리 주소를 저장한는 변수, 즉 객체를 참조하는 데 사용됨
  • 실제 객체 데이터를 직접 저장하지 않고 객체가 메모리에 위치한 주소만 저장
  • 특징
    • 객체와 연결
      • 레퍼런스 변수는 new키워드 등을 통해 생성된 객체를 가리킴
    • 동적 메모리 사용
      • 레퍼런스 변수가 가리키는 객체는 힙(Heap)메모리에 저장됨
    • null값 가능
      • 초기화되지 않은 레퍼런스 변수는 null값을 가질 수 있음
      • null값을 참조하려면 NullPointerException이 발생
    • 두 레퍼런스 변수가 동일한 객체를 가리킬 수 있음
      • 한 레퍼런스 변수를 통해 객체를 수정하면 다른 레퍼런스 변수도 수정됨
  • 예제

    •   public class Example{
            public static void main(String[] args) {
                String str = "Hello"; //str은 String객체를 참조하는 레퍼런스 변수
                System.out.println(str.length()); //참조된 객체의 메서드 호출 가능
      
                str = null; //str이 아무 객체도 참조하지 않음
                //System.out.println(str.length()); //NullPointerException 발생
            }
        }
      
    •   public class Example {
            public static void main(String[] args) {
                int[] numbers = {1,2,3};
                int[] ref = numbers; //같은 객체 참조
                ref[0] = 100; //참조를 통해 객체 수정
                System.out.println(numbers[0]); //출력: 100
            }
        }
      

Java 변수 비교: static, 지역 변수, 레퍼런스 변수의 특징과 차이점

static 변수와 지역 변수 비교

특징static 변수지역 변수
범위(Scope)클래스 전체에서 접근 가능 (전역적)선언된 블록(예: 함수) 내에서만 유효
수명(Lifetime)프로그램 종료 시까지 유지블록 실행이 끝나면 소멸
공유모든 객체가 같은 값을 공유각 함수 호출마다 독립적으로 생성
메모리 위치메서드 영역(Method Area)스택(Stack) 메모리

static 변수와 레퍼런스 변수 비교

특징static 변수레퍼런스 변수
저장 내용클래스 수준에서 공유되는 데이터객체의 메모리 주소를 저장
초기화 여부명시적 초기화가 없으면 기본값으로 초기화됨초기화되지 않으면 null 값을 가짐
수명클래스 로드부터 프로그램 종료까지 유지변수의 유효 범위 내에서만 사용 가능
클래스 의존성클래스와 연결 (객체와 무관)객체를 가리킴 (객체가 없으면 의미 없음)
메모리 위치메서드 영역(Method Area)스택(지역 변수일 때) 또는 힙(객체를 참조할 때)

지역 변수와 레퍼런스 변수 비교

특징지역 변수레퍼런스 변수
저장 내용값 자체객체의 메모리 주소
유효 범위선언된 블록 내객체가 참조되는 동안
메모리 위치스택 메모리힙 메모리에 저장된 객체를 참조
초기화 필요성명시적 초기화 필요초기화되지 않은 경우 null 값을 가질 수 있음