※ JVM 메모리 구조
- JVM은 크게 Gabage Collector, Execution Engine, Class Loader, Runtime Data Area 4가지 영역으로 이루어진다.
- .java -> (javaC) -> .class -> javaByteCode로 컴파일 된다.
- 이렇게 컴파일된 ByteCode들은 Class Loader가 메모리가 할당된 Runtime Data Area로 코드들을 적재시킨다.
- Runtime Data Area은 5가지로 구성된다.
- Method Area
- Static Area라고 한다.
- 초기 로드시 필요한 정보들 즉 필요한 패키지 클래스, 인터페이스, 상수, static변수,final 변수, 클래스 멤버 변수 등 로드되고 난 후 메모리에 항상 상주하고 있는 영역이다.
- Heap
- 메소드 안에서 사용되는 객체들의 영역으로 new연산을 통해 생성된 객체,배열,Immutable 한 객체 등의 메모리와 값이 저장된다.
- Stack
- 클래스 안 메서드 실행 시 해당 영역이 할당되며 메서드에서 직접 사용할 지역변수, 파라미터, 리턴 값, 참조 변수 일 경우 주소 값들이 저장된다.
- PC Register
- Native Method Stack
- Method Area
static이란
- 메모리에 한 번 할당되어 프로그램이 종료할 때 까지 해제되지 않는 것을 의미한다.
- 우리가 만든 class는 static영역에 생성되고 , new 연산을 통해 Heap영역에 생성되어 GC에 관리를 받는다.
- static 영역에 할당 된 메모리는 모든 객체가 공유하는 메모리라는 장점을 지닌다.
- static을 난무하게 되면 메모리가 할당 된 채로 존재하므로 자주 사용하게 되면 시스템의 성능의 악영향을 준다.
static 변수의 특징
- 객체를 생성하지 않아도 static 자원에 접근이 가능하다.
- 클래스 로더가 .class 파일을 탐색 중 static 키워드를 보는 순간 객체가 생성되지 않아도 항상 메모리를 할당해야하 하는 멤버로 보고 Method Area(Static Area)에 메모리를 할당한다.
- 그래서 static 키워드가 붙은 멤버들은 객체(인스턴스)에 소속된 변수가 아니라 클래스에 소속된 변수이기 때문에 클래스 변수 혹 클래스 메소드라고 부른다.
- new를 통해 객체를 생성하면 각 인스턴스는 서로 독립적이지만 이러한 특징때문에 static 키워드가 붙은 멤버들은 모든 객체가 메모리 영역을 공유한다.
public class MyCalculator {
public static appName = "MyCalculator";
public static int add(int x, int y) {
return x + y;
}
public int min(int x, int y) {
return x - y;
}
}
MyCalculator.add(1, 2); // static 메소드 이므로 객체 생성 없이 사용 가능
MyCalculator.min(1, 2); // static 메소드가 아니므로 객체 생성후에 사용가능
MyCalculator cal = new MyCalculator();
cal.add(1, 2); // o 가능은 하지만 권장하지 않는 방법
cal.min(1, 2); // o
static 변수(정적 변수)
- 메모리에 고정적으로 할당되어, 프로그램이 종료될 때 해제되는 변수
- static 변수는 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 변수로, 메모리에 한번 할당되므로 여러 객체가 해당 메모리를 공유하게 된다.
public class Person {
private String name = "person";
public void printName() {
System.out.println(this.name);
}
}
하지만 100명의 person객체를 생성하면, 100개의 동일한 person 이라는 name 이 중복해서 생성된다. 이 때 static을 사용해서 여러 객체가 하나의 메모리를 참조하도록 하면 100개의 중복 메모리를 제거하여 효율이 있어지게 된다.
private final static String name = "person";
게다가 불변하지 않는 특성도 있어 final을 추가해준다.
static 메소드
- 객체 생성 없이 호출이 가능하며, 객체에서는 호출이 불가능 하다.
- static 키워드를 만나는 순간 메모리에 적재시켜야 하는데 static 이 붙지 않은 변수를 접근하려면 에러가 난다.
- 객체를 생성해야 인스턴스 변수가 적재되기 때문에 순서적으로 맞지 않는다.
- 일반적으로 유틸리티 관련 함수들은 여러 번 사용되므로 static메소드로 구현을 하는 것이 적합한데, static메소드를 사용하는 대표적인 Util class 로는 Math가 있다.
ex) Math.max(100,1000)
※ static 이슈
- 전체 프로그램과 동일한 라이프사이클.
- 메소드 호출 시간이 짧아 진다고 무분별한 static 은 지양한다.(= 데이터 접근이 빠르다는 이유로 사용을 지양한다.)
- static 은 글로벌 변수에 가까우므로 인스턴스 변수보다 테스트가 까다롭다.
- 오버라이딩 또한 불가하여 코드의 재사용성이 떨어진다.
- GC 관리 받는 영역이 아니라서 메모리 낭비가 발생한다.
- Thread safe 하지 못한다.
- 한 스레드에서 값을 변경하는 경우 다른 모든 스레드에 영향을 받는 동시성 문제가 발생할 수 있다.
- Thread Safe하기 위해 추가적인 작업이 필요하다.
- Serialization이 불가하다.
- 객체 직렬화는 인스턴스에 대해 적용되기 때문에 클래스 자체 정보인 static 멤버는 포함되지 않는다.
'JAVA' 카테고리의 다른 글
Enum class (0) | 2021.05.17 |
---|---|
인터페이스, 추상클래스 (0) | 2021.05.16 |
가비지 콜렉터의 종류 (0) | 2021.05.03 |
Garbage Collector (0) | 2021.04.25 |
Reflection (0) | 2021.04.16 |
댓글