JAVA

static

whyWhale 2021. 5. 4.

※ 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 

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

댓글