Static Method란
자바(Java)에서 static 메소드는 클래스에 속한 메소드로, 클래스의 특정 인스턴스에 속하지 않고 클래스 레벨에서 직접 호출할 수 있는 메소드입니다. static 메소드는 클래스가 메모리에 로드될 때 생성되며, 클래스의 모든 인스턴스가 공유합니다.
static 메소드의 특징은 다음과 같습니다.
- 인스턴스를 생성하지 않고도 클래스 이름을 사용하여 직접 호출할 수 있습니다.
- static 메소드 내에서는 static 변수나 다른 static 메소드에 직접 접근할 수 있지만, 인스턴스 변수나 인스턴스 메소드에는 접근할 수 없습니다.
- static 메소드는 this 키워드를 사용할 수 없습니다. 왜냐하면 this는 현재 인스턴스를 가리키는 참조인데, static 메소드는 인스턴스와 관련이 없기 때문입니다.
- 일반적으로 유틸리티 함수나 클래스 레벨에서 관리해야 하는 작업을 수행하는데 사용됩니다.
예를 들어, Math 클래스의 sqrt 메소드는 static 메소드로, 다음과 같이 사용할 수 있습니다.
double result = Math.sqrt(25); // 결과는 5.0
여기서 sqrt 메소드는 Math 클래스의 인스턴스를 생성하지 않고도 호출할 수 있으며, 제곱근을 계산하는 유틸리티 메소드로 작동합니다.
static 메소드를 선언하는 방법은 다음과 같습니다:
public class MyClass {
public static void myStaticMethod() {
// static 메소드 내용
}
}
이제 MyClass 클래스의 myStaticMethod 메소드는 어디서든 MyClass.myStaticMethod()로 호출할 수 있습니다.
Memory load
자바에서 메모리는 크게 세 부분으로 나뉩니다: 힙(heap) 메모리, 스택(stack) 메모리 그리고 메소드(method) 메모리입니다.
- 힙 메모리(Heap Memory): 이 공간은 애플리케이션의 모든 파트에서 공유되며, 객체와 클래스의 인스턴스가 저장됩니다. 가비지 컬렉터는 이 영역을 관리하며, 더 이상 참조되지 않는 객체들을 정리합니다.
- 스택 메모리(Stack Memory): 이 공간은 각 쓰레드마다 별도로 할당되며, 쓰레드가 시작될 때 생성됩니다. 스택 메모리는 메소드 호출과 로컬 변수를 관리합니다. 각 메소드 호출은 스택 프레임이라는 블록을 생성하고, 메소드가 종료되면 해당 블록은 스택에서 제거됩니다.
- 메소드 영역(Method Area): 클래스 로더에 의해 클래스가 처음 로딩될 때 생성되며, 클래스와 인터페이스의 메타데이터, 정적 변수, 상수, JIT 컴파일러에 의해 컴파일된 코드 등이 저장됩니다.
static 변수와 메소드 메소드 영역(Method Area)에 저장됩니다. 메소드 영역은 클래스 레벨의 정보(클래스 구조, 상수, static 변수 등)를 저장하는 곳입니다.
이러한 각 영역은 자바 애플리케이션이 실행될 때 서로 다른 목적으로 사용되며, static 변수와 메소드는 메소드 영역에 위치하여 모든 클래스 인스턴스와 쓰레드에 의해 공유됩니다.
Thread safe?
자동으로 공유된다해서 자바에서 static 메소드 자체가 쓰레드 안전(thread-safe)하다고 말할 수는 없습니다. 쓰레드 안전 여부는 메소드가 어떻게 작성되었는지에 따라 달라집니다.
static 메소드는 클래스의 인스턴스와 무관하게 클래스 자체에 속해 있으며, 모든 인스턴스가 공유합니다. 만약 static 메소드가 변경 가능한 공유 상태(예: static 변수)를 사용하고, 여러 쓰레드가 동시에 이 메소드를 호출한다면, 동기화(synchronization) 문제가 발생할 수 있습니다.
아래 예제는 static 메소드 뿐만이 아니라 일반적으로 많이 쓰이는 Race condition 예제입니다.
public class UnsafeCounter {
private static int counter = 0;
public static void increment() {
counter++; // 쓰레드에 안전하지 않은 연산
}
public static int getCounter() {
return counter;
}
}
위와 같은 예제를 multi threading 환경에서 돌려보면 counter 변수의 값이 예상치 못하게 변경될 수 있습니다. 이는 counter++ 연산이 원자적(atomic)이지 않기 때문입니다.
즉, static은 thread-safe 하지 않습니다.