JVM(Java Virtual Machine)은 자바 프로그램이 실행되는 환경을 제공하며, 이를 위해 여러 메모리 영역을 사용한다. 각 영역은 특정 유형의 데이터를 저장하고 관리하는 역할을 한다.
Heap: 모든 객체와 배열이 저장되는 곳이며, Garbage Collector가 관리하는 영역. 모든 JVM 스레드에 의해 공유되는 공간이다.
Stack: 메소드 호출과 지역 변수 등의 정보를 저장하고 각 스레드마다 별도의 스택을 가진다.
Program Counter(PC)는 현재 수행 중인 프로그램 위치를 가리킨다. 따라서 현재 프로그램이 실행되고 있는 상태를 파악할 수 있도록 실행 중인 메모리 공간이다.Method Area(static-zone): 클래스 정보, 상수, static 변수 등이 저장되는 영역으로 모든 스레드가 공유하는 영역이다. 메서드의 바이트 코드가 할당되며 static-zone과 non-static-zone으로 나뉜다.
Runtime Constant Pool: 클래스 또는 인터페이스의 상수 및 동적 참조를 저장하는 영역으로, 클래스 파일의 constant_pool 테이블의 런타임 표현이다.
static 멤버는 클래스에 속하며, 모든 인스턴스가 공유하는 변수나 메소드이다.
JVM의 클래스 로더는 자바 가상 머신(JVM)에서 컴파일된 자바의 클래스 파일(*.class)을 동적으로 로드하고 JVM의 메모리 영역인 Runtime Data Areas에 배치하는 작업을 수행한다.

class 파일의 로딩 순서는 Loading -> Linking -> Initialization이다.
① Loading: 실행할 클래스 파일을 가져와 JVM 메모리에 로드.
② Linking: 클래스 파일을 사용하기 위해 검증
③ Initialization: 초기화, 즉 클래스 변수들을 적절한 값으로 초기화.

메서드가 호출되면, JVM의 Call Stack Frame Area(스택 영역)에 해당 메서드를 위한 프레임이 생성된다. 즉, 각 메서드 호출마다 고유의 프레임이 생성되어, 메서드의 실행 상태를 관리한다. 이 프레임 내에는 메서드의 지역 변수, 매개변수, 리턴 값 등이 저장된다.

public class StaticAll{
private StaticAll(){}
public static ...
public static ...
public static ...
}

클래스명.멤버명으로 접근할 수 있지만, 인스턴스 생성 후 접근할 수도 있다. 하지만 이는 바람직한 접근법이 아니므로 모든 멤버가 static일 때 후자의 접근을 막기 위해서 의도적으로 생성자를 private 접근제어자를 이용하여 인스턴스를 생성하지 못하게 할 수 있다.인스턴스로 접근하여 static 멤버를 사용하는 경우에도 실제로는 Method Area에 등록된 static 멤버를 참조하게 된다. 이는 컴파일러가 해당 멤버를 클래스명을 통해 접근하는 것으로 변환하여 실행하기 때문이다. 즉, 인스턴스로 접근하더라도 실제로는 Method Area에 등록된 static 멤버를 가져오게 된다.
public class Test{
// ...
public static int a=1;
public static void testMethod(){System.out.println("test");}
// ...
}
public class Main{
public static void main(String[] args){Test.testMethod();}
}
Test 클래스의 정적 메서드(testMethod())가 호출되면 클래스 로딩 과정에서 Test 클래스의 모든 정적 멤버(static member)가 메모리에 로드된다.
이는 해당 클래스의 정적 멤버가 호출되는지 여부와 관계없이 발생하므로 a는 testMethod()와 같은 클래스인 Test 클래스의 멤버이므로 함께 메모리에 로드된다.
a의 로딩클래스 로더(Class Loader)가 Test 클래스를 로드하면서 해당 클래스 파일을 분석. 분석 과정에서 a라는 정적 변수를 인식하고, 이를 메서드 영역(Method Area)에 할당. 변수의 타입과 초기값이 함께 저장된다.
testMethod()의 로딩클래스 로더가 Test 클래스를 분석하면서 testMethod()라는 정적 메서드를 인식하고, 이를 메서드 영역에 할당. 메서드의 바이트 코드와 메서드 시그니처(리턴 타입, 매개변수 등)가 함께 저장된다.