Java의 JVM이란

9216 단어 JVMJVM

1. JVM개념 및 구성요소

1-1. 개념 및 역할

  • Java Virtual Machine , 자바 가상 머신을 뜻하는 말로
    Java 바이트 코드를 OS에 맞게 해석하고, Garbage Collector을 통한 메모리 관리를 수행한다.

1-2. JVM 구성요소

Class Loader

  • Runtime 시점에 JVM으로 .class 파일을 로드하고,
    링크를 통해 Runtime Data Area에 배치하는 작업 수행한다.
  • .jar 또는 .war파일 내 저장된 .class 파일들을 JVM위에 올리고, 사용하지 않는 .class 파일들은
    메모리에서 삭제한다.

Execution Engine

  • Runtime Data Area에 .class 파일을 실행시키는 역할을 수행한다.
  • 실행하는 방법은 두 가지로 나뉜다.
    1. Interpreter(인터프리터)

      • Execution Engine은 바이트 코드를 명령어 단위로 읽어서 실행하므로 속도가 느리다.
    2. JIT(Just In Time)

      • 인터프리터 방식의 단점을 보완하기 위해 도입된 컴파일러이다.
      • 처음에는 인터프리터방식으로 실행하다가 적절한 시점에 바이트코드 전체를
        컴파일하여 네이티브코드로 변경한다. 네이티브 코드는 캐시에 보관되므로
        한번 컴파일된 코드는 빠르게 수행된다.
      • JIT컴파일러가 컴파일하는 과정은 인터프리터보다 오래걸린다.
        하지만 캐시를 통해 한번 컴파일된 코드는 빠르게 수행된다.

Garbage Collector

  • heap 영역에서 더 이상 사용하지 않는 영역을 탐지하여 자동으로 해지한다.

Runtime Data Area

  • OS에서 할당받은 메모리 공간이다.

  • PC Register

    Thread 가 시작될 때 생성되며 생성될 때마다 생성되는 공간으로 스레드마다 하나씩 존재한다. Thread가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행 중인 JVM 명령의 주소를 갖는다.

  • JVM stack

    프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역이다. 각종 형태의 변수나 임시 데이터, 스레드나 메소드의 정보를 저장한다. 메소드 호출 시마다 각각의 스택 프레임(그 메서드만을 위한 공간)이 생성된다. 메서드 수행이 끝나면 프레임 별로 삭제를 한다. 메소드 안에서 사용되는 값들(local variable)을 저장한다. 또 호출된 메소드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장한다.

  • Native method stack

    자바 프로그램이 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역이다. JAVA가 아닌 다른 언어로 작성된 코드를 위한 공간이다. JAVA Native Interface를 통해 바이트 코드로 전환하여 저장하게 된다. 일반 프로그램처럼 커널이 스택을 잡아 독자적으로 프로그램을 실행시키는 영역이다. 이 부분을 통해 C code를 실행시켜 Kernel에 접근할 수 있다.

  • Method Area (= Class area = Static area)

    클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간. 올라가게 되는 메소드의 바이트 코드는 프로그램의 흐름을 구성하는 바이트 코드이다. 자바 프로그램은 main 메소드의 호출에서부터 계속된 메소드의 호출로 흐름을 이어가기 때문이다. 대부분 인스턴스의 생성도 메소드 내에서 명령하고 호출한다. 사실상 컴파일 된 바이트코드의 대부분이 메소드 바이트코드이기 때문에 거의 모든 바이트코드가 올라간다고 봐도 상관없다. 이 공간에는 Runtime Constant Pool이라는 별도의 관리 영역도 함께 존재한다. 이는 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.

  • Heap( 힙 영역 )

    객체를 저장하는 가상 메모리 공간이다. new연산자로 생성된 객체와 배열을 저장한다. 물론 class area영역에 올라온 클래스들만 객체로 생성할 수 있다. 힙은 세 부분으로 나눌 수 있다.

    • per 영역 (Permanent Generation)

      • 생성된 객체들의 정보의 주소값이 저장된 공간이다. Class loader에 의해 load되는 Class, Method 등에 대한 Meta 정보가 저장되는 영역이고 JVM에 의해 사용된다. Reflection을 사용하여 동적으로 클래스가 로딩되는 경우에 사용된다. 내부적으로 Reflection 기능을 자주 사용하는 Spring Framework를 이용할 경우 이영역에 대한 고려가 필요하다.
    • Young 영역

      • Young 영역은 3개의 영역으로 다시 나뉜다. Eden, Survivor(2개) 영역
      • Eden : 객체들이 최초로 생성되는 공간
      • Survivor 0 / 1 : Eden에서 참조되는 객체들이 저장되는 공간
    • Old 영역

      • New area에서 일정 시간 참조되고 있는, 살아남은 객체들이 저장되는 공간 Eden영역에 객체가 가득차게 되면 첫번째 GC(minor GC)가 발생한다. Eden영역에 있는 값들을 Survivor 1 영역에 복사하고 이 영역을 제외한 나머지 영역의 객체를 삭제한다.
      • 인스턴스는 소멸 방법과 소멸 시점이 지역 변수와는 다르기에 힙이라는 별도의 영역에 할당된다. 자바 가상 머신은 매우 합리적으로 인스턴스를 소멸시킨다. 더이상 인스턴스의 존재 이유가 없을 때 소멸시킨다.

2. 컴파일 하는 방법

  • 컴파일을 수행한다는 것은, .java파일을 .class(바이트코드)파일로 만드는것을 의미한다.

    javac 파일명.java
  • javac 옵션들


3. 실행하는 방법

java 파일명.class
  • 명령어 실행 시 클래스로더가 해당 .class 파일을 JVM으로 로드한다.

4. 바이트 코드란?

  • JVM이 이해할 수 있는 언어로 변환된 자바 소스 코드이다.

  • 자바가 OS에 독립적인 이유이다. JVM이 이해할 수 있는 바이트코드로 제공되며
    JVM이 있으면 어느 OS든 실행할 수 있기 때문이다.

    • OS마다 다른 JVM이 존재한다.(윈도우 JVM, LINUX JVM, MAC JVM 등등)

5. 자바 애플리케이션 실행 과정

  1. 애플리케이션이 실행되면 JVM은 OS로부터 필요한 만큼 메모리를 할당받는다.

  2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어 바이트 코드(.class)로 변환시킨다.

  3. Class Loader를 통해 바이트코드를 JVM으로 로드한다.

  4. 로딩된 바이트코드들은 Excution engine을 통해 해석된다.

  5. 해석된 바이트 코드는 Runtime Data Areas 영역에 배치되어 수행된다.


6. JDK JRE 차이

  • JDK = JRE + @(개발에 필요한 도구들)

  • JRE는 읽기전용, JDCK는 읽기/쓰기 전용

JDK(Java Delvelopment Kit)

  • 자바파일을 컴파일하고 개발할 수 있도록 해주는 개발환경 세트이다.

  • JDK는 JRE와 JVM을 포함하고 개발에 필요한 컴파일러, 디버거 등 도구들을 포함한다.

JRE(Java Runtime Environment)

  • 자바를 개발하지는 않지만, 자바 애플리케이션을 실행하기 위해서 필요하다.

  • 컴파일된 자바 애플리케이션들을 실행할 수 있다.


7. Garbage Collector

  • GC에 대해 간단히 알아보고 넘어가자.

먼저 Garbage에 대해 알아보자

  • Garbage는 정리되지 않은 메모리, 유효하지 않은 메모리 주소를 말한다.
String[] array = new String[2];

array[0] = '0';
array[1] = '1';

array = new String[] {'G', 'C' };
  • 맨 아래 코드 String 배열이 new 연산자로 생성되기 전 0,1 값은 다시 참조할수 있는가?
    없다. 주소를 잃어버려 사용할수 없는 메모리가 된다.

  • 프로그래밍 언어에서는 Danling Object, 자바에서는 Garbage라고 부른다.

Garbage Collector 란?

  • 메모리가 부족할때 Garbage를 정리해주는 프로그램과 같다.

  • 가비지 컬렉션(Garbage Collection)을 수행한다. 즉
    프로그램이 동적으로 할당했던 메모리 영역중 필요없는 영역을 해제하는 기능을 수행한다.

동작 시기

  • GC(Garbage Collector)는 위에서 보았듯이 JVM안에 존재한다.

  • 그래서 기본적으로 Runtime에 동작하며 아래 조건 중 하나라도 충족하면 JVM은 GC를 실행한다.

    1. OS로부터 할당 받은 시스템의 메모리가 부족한경우
    2. 관리하고 있는 힙에서 사용되는 메모리가 허용된 임계값을 초과하는 경우
    3. 프로그래머가 직접 GC를 실행하는 경우
      • 이 경우는 시스템의 성능에 매우 큰 영향을 끼치므로 절대로 사용하지 말아야 한다.

동작 과정

  • GC 과정을 Mark and Sweep이라고도 부른다.

  • GC가 모든 변수 또는 Reachable 객체를 스캔하면서 각각 어떤 객체를 참조하고 있는지
    찾는 과정을 Mark라고 한다.

  • 이 과정에서 Stop the World가 발생한다.

    • Stop the World
      • GC 실행을 위해 JVM이 애플리케이션 실행을 멈추는 것을 의미한다.
      • GC를 실행하는 쓰레드를 제외한 모든 쓰레드들이 작업을 멈춘다.
      • 대개 GC를 튜닝한다 할 때 stop the World 시간을 줄이는 것을 말한다.
  • Mark 과정 이후 참조되고 있지 않는 객체들을 힙에서 제거하는 과정이 Sweep이다.

Minor GC와 Major GC

  • Minor GC
    • 힙의 Young 영역에서 발생한 GC
  • Major GC
    • 힙의 Old, Perm 영역에서 발생한 GC
💡 GC는 나중에 따로 더 자세히 학습하자.

#ref

좋은 웹페이지 즐겨찾기