개발 & 데이터베이스/JAVA

자바 지역변수, 전역변수, 정적(static) 변수의 차이점 (Java 8 이후의 JVM 구조)

K.두부 2023. 4. 24. 13:00
반응형

자바에서는 선언 위치에 따라서 크게 지역 변수와 전역 변수 2개로 나눌 수 있다.

전역 변수에는 클래스 변수와 인스턴스 변수가 있다.

 

1. 지역 변수 (Local Variable)

public class Main {
    public static void main(String[] args) {
        int localVar = 10;
        System.out.println(localVar); // 10
    }
}

메서드 내에서 선언된 변수로 해당 메서드 내에서만 사용이 가능하다. 메서드 호출이 끝나면 소멸되고, 초기화하지 않으면 컴파일 에러가 발생한다.

 

2. 전역 변수

전역 변수에는 클래스 변수와 인스턴스 변수가 존재한다.

 

[인스턴스 변수]

public class Main {
    public int globalVal;
    
    public static void main(String[] args) {
        Main main = new Main();
        main.globalVal = 10;
        System.out.println(main.globalVal); // 10
    }
}

클래스 내부에 선언된 변수로 해당 클래스의 모든 메서드에서 사용이 가능하다. 객체 생성 시에 Heap 메모리 영역에 할당되며, 객체가 소멸할 때까지 유지된다. 또한, 기본값으로 초기화가 되므로 별도의 초기화가 없어도 컴파일 에러가 발생하지 않는다.

 

[클래스 변수]

public class Main {
    public static int staticVal;
    
    public static void main(String[] args) {
        staticVal = 10;
        System.out.println(staticVal); // 10
    }
}

 프로그램 실행 시에 Method Area(Static Area) 메모리 영역에 할당되며, 프로그램이 종료될 때까지 유지된다. 때문에 static키워드를 남발하게 되면 메모리 초과, 속도 저하 등의 문제가 발생할 수 있다. 또한, 별도의 인스턴스 생성 없이 호출이 가능하다.

 

JVM 구조 (Java 8 전후 비교)

출처: https://steady-coding.tistory.com/603

Java 8 이전에는 정적 객체들은 Heap 영역에서 Permanent Generation 영역에 저장되었다. Permanent 영역은 메타 데이터, 정적 변수 등이 저장되며, 메서드 영역에 해당된다. Garbage Collection의 대상이 아니다.

 

 

출처: https://steady-coding.tistory.com/603

Java 8 이후에 Heap 영역은 Permanent 영역이 사라지고, Metaspace라고 하는 네이티브 메모리에서 Permanent가 저장하던 정보를 들고 있도록 변경되었다. Garbage Collection의 대상이 된다.

 

Permanent 영역에서 관리하던 클래스 메타 데이터는 Metaspace로 옮겨지고, 정적 변수는 힙 영역에 옮겨짐으로써 Java 8 이후부터 static 변수는 Heap 영역에서 관리하게 된다.

 

 

✅ Permanent 영역이 사라지고 Metaspace가 생긴 이유

: 각 종 클래스 메타 데이터를 Heap 영역에서 관리하다 보니 해당 영역에 들어간 데이터의 사이즈를 계산하기 어려워서 OOM ("java.lang.OutOfMemoryError: PermGen space") 에러가 빈번하게 발생했다. 이를 방지하기 위해서 메타 데이터는 네티이브 메모리에서 관리하고, static 변수만 Heap 영역에서 관리하게 됨.

 

Static 사용하면 좋은 경우

1. 상수 정의

: 객체 내에서 변수를 여러 번 정의하기 보단 한 번의 정적 변수를 생성하는 것이 메모리를 절약할 수 있다.

static final int A = 5;

 

2. 유틸리티 클래스 정의

: 인스턴스 메서드와 인스턴스 변수를 제공하지 않고 데이터 처리를 위한 정적 메서드만 존재하는 클래스로 애초에 객체의 상태를 이용할 생각이 없는 경우에 사용하면 좋다.

 

대표적인 예로 Math 클래스, StringUtils 클래스(isEmpty, toUpperCase 등), DataUtils 클래스(now, toString, compare 등)가 있다. 

 

 

 

 

 


● 참고

https://steady-coding.tistory.com/603

반응형