[20210615] JVM

Java Virtual Machine에 대해 알아보자.

JVM은 운영체제 위에서 동작한다

자바 가상머신은 운영체제 위에서 실행되는 하나의 프로그램이다. 자바 프로그램은 자바 가상머신 위에서 실행되는 프로그램이다.

결국 자바 가상머신은 운영체제가 할당해준 메모리 공간을 기반으로 자기 자신(자도 실행하면서, 자바 응용 프로그램의 실행도 돕는다.

JVM 구성

Class Loader

  • JVM내로 클래스(.class파일)를 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈.
  • Runtime 시에 동적으로 클래스를 로드한다.
  • jar파일 내 저장된 클래스들을 JVM위에 탑재하고 사용하지 않는 클래스들은 메모리에서 삭제한다.
  • (컴파일러 역할) 자바는 동적코드, 컴파일 타임이 아니라 런타임에 참조한다.
  • 즉, 클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링크한다.

Execution Engine

  • 클래스를 실행시키는 역할
  • 클래스 로더가 JVM내의 런타임 데이터 영역(메소드 영역)에 바이트 코드를 배치시키고, 바이트 코드는 실행엔진에 의해 실행된다.
  • 바이트코드를 실제로 JVM내부에서 기계가 실행할 수 있는 형태로 변경. 이때 Interpreter 방식 or JIT 컴파일러 방식을 사용

Interpreter

  • 자바 바이트 코드를 명령어 단위로 읽어서 실행
  • 인터프리터 언어의 단점을 그대로 갖고 있음(한 줄 씩 수행하기 때문에 느림)

JIT(Just In Time)

  • 인터프리터 방식의 단점을 보완하기 위해 도입
  • 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경, 이후에는 네이티브 코드로 직접 실행하는 방식
  • 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행가능
  • 물론 JIT 컴파일러가 컴파일하는 과정은 바이트코드를 인터프리팅하는 것보다 훨씬 오래걸리기 때문에 JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 수준을 넘을 때에만 컴파일을 수행.

Garbage collector

  • Garbage Collection을 수행하는 모듈(쓰레드)이 있다.
  • Heap 영역의 오브젝트 중 stack 에서 도달 불가능한 (Unreachable) 오브젝트들은 가비지 컬렉션의 대상이 된다.
  • Garbage Collection 과정은 Mark and Sweep 이라고도 한다.
  • JVM의 Garbage Collector 가 스택의 모든 변수를 스캔하면서 각각 어떤 오브젝트를 레퍼런스 하고 있는지 찾는과정이 Mark
  • 첫번째 단계인 marking 작업을 위해 모든 스레드는 중단되는데 이를 stop the world 라고 부르기도 한다.
  • 그리고 나서 mark 되어있지 않은 모든 오브젝트들을 힙에서 제거하는 과정이 Sweep

JVM의 메모리 관리

자바 가상머신도 자바 프로그램의 실행을 위해서 메모리 관리를 해야만 한다. 가상머신은 메모리 공간을 크게 세 개의 영역(메소드, 스택, 힙)으로 나눈다.

메소드 영역 : 메소드의 바이트코드, static 변수 스택 영역 : 지역변수, 매개변수 힙 영역 : 인스턴스

메소드 영역

소스파일을 컴파일 할 때 생성되는, 자바 가상머신에 의해 실행이 가능한 코드를 가리켜 ‘자바 바이트코드(bytecode)’라 한다. 이러한 바이트코드들도 메모리 공간에 저장되어 있어야 실행이 가능하다. 따라서 실행의 흐름을 형성하는 메소드의 바이트코드들은 메소드 영역에 저장된다. 그리고 static으로 선언되는 클래스 변수도 이 영역에 할당이 된다.

바이트코드와 static 변수가 메소드 영역에 저장되는 시점이 바로 ‘클래스가 메모리에 올려지는 시점’이다. 즉 메소드 영역은 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간이다.

스택 영역

스택은 지역변수와 매개변수가 저장되는 공간이다. 이 둘의 공통적인 특징은 메소드 내에서만 유효한 변수들이다. 즉 스택은 프로그램의 실행과정에서 임시로 할당되었다가, 메소드를 빠져나가면 바로 소멸되는 특성의 데이터 저장을 위한 영역이다.

힙 영역

인스턴스는 힙 영역에 할당이 된다. 인스턴스를 스택이 아닌 힙에 할당하는 이유는 인스턴스의 소멸방법과 소멸시점이 지역변수와는 다르기 때문이다. 인스턴스를 생성하게되면 인스턴스만 만들어 지는 것이 아닌 인스턴스를 참조하고 있는 참조변수도 만들어진다. 즉, 힙 영역에 인스턴스가 만들어지고 해당 인스턴스를 참조하는 참조변수는 스택 영역에 만들어진다.


출처

윤성우 저, 난 정말 java를 공부한 적이 없다구요 https://yaboong.github.io/java/2018/06/09/java-garbage-collection/ https://asfirstalways.tistory.com/158