[JAVA] JAVA 메모리 모델과 변수의 종류 : static, 지역변수, 레퍼런스 변수 이해하기
in JAVA
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)의 메모리 구조 중 하나
- 클래스 수준의 정보를 저장하는 영역
- 저장되는 데이터 종류
- 클래스 정보
- 클래스의 이름, 부모 클래스, 접근 제어자 등의 메타데이터
- 클래스 변수 (static 변수)
- 클래스가 로드될 때 메모리에 할당되며 모든 객체에서 공유됨
- 메서드 정보
- 메서드의 이름, 리턴 타입, 매개변수 타입 등
- 메서드의 바이트코드 포함
- 상수 (Constant Pool)
- 컴파일 시 생성된 상수(문자열, 숫자 리터럴 등)와 참조(메서드 참조, 클래스 참조)가 저장됨
- 런타임 상수 풀(Runtime Constant Pool)
- 런타임 중에 동적으로 생성된 상수와 참조.
- 클래스 정보
- 저장되는 데이터 종류
- 특징
- JVM내에서 유일 : 모든 스레드가 공유
- 수명 : JVM이 종료될 때까지 유지
- Garbage Collection 대상 아님 : 클래스 정보는 명시적으로 제거되지 않음
지역변수 & 레퍼런스 변수
지역변수 (Local Variable)
- 특정 블록이나 함수 안에서만 선언되고 사용가능한 변수
- 해당 블록이나 함수가 실행을 마치면 메모리에서 삭제되며, 외부에서 접근 불가능
- 특징
- 유효 범위 (Scope)
- 변수가 선언된 블록(중괄호 {}로 감싸진 영역) 내에서만 유효
- 초기화 필요
- 지역변수는 자동으로 초기화 되지 않음
- 메모리 관리
- 지역변수는 함수 호출시 생성되고, 함수 종료 시 자동으로 소멸됨
- 일반적으로 스택 메모리 사용
- 유효 범위 (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 값을 가질 수 있음 |