JVM 메모리 구조
JVM : 자바 바이트 코드들을 OS에서 어떻게 실행할 지에 대한 표준 스펙
static 키워드를 이해하기 위해선 JVM의 메모리 구조 및 실행 단계에 대한 선행되어야 한다.
JVM 구조
Garbage Collector : Heap 영역에 더이상 사용 하지 않는 객체 제거
Execution Engine : .class 파일을 하나의 명령 단위로 읽어 컴퓨터가 이해할 수 있는 기계어로 번역 후 실행
Class Loader : .java 파일을 .class로 (바이트코드)로 컴파일된 바이트 코드들을 운영체제를 통해
메모리를 할당 받아둔 Runtime Data Area로 적재하는 역할
Runtime Data Area : JVM 메모리 영역으로 OS로 부터 별도로 메모리 공간을 할당 받고 JAVA 어플리케이션을
실행할 때 사용 (Method Area, Heap Area, StackArea, PC register, Native Method Stack)
static을 이해하 데 필요한 3가지 영역
- Method Area(Static Area)는 클래스, 인터페이스, static 변수, 멤버 변수 등 로드 된 후 메모리에 상주하고 있는 영역이다.
- Stack Area는 클래스 안 메서드 실행 시 영역이 할당 되며 메서드에서 직접 사용할 주소 값들이 저장
- Heap Area는 메서드 안에서 사용되는 객체들을 위한 영역으로 new를 통해 생성된 객체, 배열, immutal 객체 들의 메모리와 값 저장
Static 과 메모리 구조
- 클래스 로더가 .class 파일을 탐색 중 static 키워드를 보는 순간 객체가 생성되지 않아도 항상 메모리를 할당해야 하는 멤버로 보고
Method Area에 메모리를 할당한다. 그래서 static 키워드가 붙은 멤버들은 객체(인스턴스)에 소속된 변수가 아니라 클래스에 소속된 변수이기 때문에 클래스 메서드라고 부른다. 즉, 모든 객체가 메모리 영역을 공유한다.
필드란?
- 클래스의 필드란 클래스에 포함된 변수
- 선언된 위치에 따라 구분
- 클래스 변수 (static variable)
- 인스턴스 변수(instance variable)
- 지역 변수 (local variable)
class Car {
static int modelOutput; // 클래스 변수
String modelName; // 인스턴스 변수
void method() {
int something = 10; // 지역 변수
}
}
클래스, 인스턴스 변수는 타입에 맞게 자동 초기화
*지역 변수는 초기화 하지 않으면 오류 발생 *
필드 구분
클래스 변수는 인스턴스를 생성하지 않고 바로 사용 가능 (공유 변수라고도 한다.)
클래스 변수는 해당 클래스의 모든 인스턴스가 공유해야 하는 값을 유지하기 위해 사용
반면, 인스턴스 변수는 인스턴스마다 가져야 하는 고유의 값을 유지하기 위해 사용
class Field {
static int classVar = 10; // 클래스 변수 선언
int instanceVar = 20; // 인스턴스 변수 선언
}
public class Member01 {
public static void main(String[] args) {
int var = 30; // 지역 변수 선언
System.out.println(var + "\n"); // 지역 변수 참조
Field myField1 = new Field(); // 인스턴스 생성
Field myField2 = new Field(); // 인스턴스 생성
System.out.println(Field.classVar); // 클래스 변수 참조
System.out.println(myField1.classVar);
System.out.println(myField2.classVar + "\n");
myField1.classVar = 100; // 클래스 변수의 값을 변경
System.out.println(Field.classVar); // 클래스 변수 참조
System.out.println(myField1.classVar);
System.out.println(myField2.classVar + "\n");
System.out.println(myField1.instanceVar); // 인스턴스 변수 참조
System.out.println(myField2.instanceVar + "\n");
myField1.instanceVar = 200; // 인스턴스 변수의 값을 변경
System.out.println(myField1.instanceVar); // 인스턴스 변수 참조
System.out.println(myField2.instanceVar);
}
}
클래스 변수 참조는 인스턴스를 여러개 생성해도 같은 값이 나오지만,
인스턴스 변수 참조는 인스턴스 마다 고유의 값을 갖게 된다.
메서드란?
- 어떠한 작업을 수행하기 위한 명령문의 집합
- static 키워드의 여부에 따라 구분
- 클래스 메서드 (static method)
- 인스턴스 메서드 (instance method)
class Car {
boolean door; // 인스턴스 변수
void openDoor() { // 인스턴스 메소드
door = true;
}
static void toggleDoor(boolean d) { // 클래스 메소드
return !d;
}
}
메서드 구분
class Method {
int a = 10, b = 20; // 인스턴스 변수
int add() { return a + b; } // 인스턴스 메소드
static int add(int x, int y) { return x + y; } // 클래스 메소드
}
public class Member02 {
public static void main(String[] args) {
System.out.println(Method.add(20, 30)); // 클래스 메소드의 호출
Method myMethod = new Method(); // 인스턴스 생성
System.out.println(myMethod.add()); // 인스턴스 메소드의 호출
}
}
클래스 메서드는 클래스 변수와 마찬가지로 인스턴스를 생성하지 않고도 바로 사용 가능하다.
즉, 클래스 메서드는 메서드 내부에서 인스턴스 변수를 사용할 수 없다.
참고자료 : https://honbabzone.com/java/java-static/ http://tcpschool.com/java/java_member_method