고딩왕 코범석

JVM 정리 본문

Language & Framework/JAVA

JVM 정리

고딩왕 코범석 2021. 12. 11. 17:26
반응형

Java Virtual Machine

역할?

자바 애플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행하며, Java와 OS 사이에서 중개자 역할을 담당하여, OS에 구애받지 않고 재사용이 가능하다. 그리고 전반적으로 메모리 관리, Garbage Collection 기능을 수행한다.

실행 과정

  1. 프로그램 실행 시, JVM은 OS로 부터 이 프로그램이 필요로 하는 메모리를 할당 받음. 이 때, JVM은 이 메모리를 용도에 따라 여러 영역으로 나눠 관리
  2. 자바 컴파일러(javac)가 자바 소스 코드(XXX.java)를 읽어 들여 바이트코드(.class)로 변환
  3. Class Loader를 통해 .class 파일들을 JVM으로 로딩
  4. 로딩된 class 파일들은 실행 엔진에 의해 해석
  5. 해석된 바이트코드는 Runtime Data Areas 에 배치되어 실질적인 수행

이러한 실행 과정 속에서 JVM은 필요에 따라 Thread Synchronization과 GC 같은 관리 작업 수행

JVM Architecture

image

1. Class Loader SubSystem

image


클래스 로더는 JRE의 일부이며, JVM이 런타임에 클래스를 요청할 때, 클래스 로더는 클래스를 찾고 정규화된 이름을 사용해 로드한다. JVM은 Applicatoin ClassLoader에게 최초의 요청을 보내며 클래스가 아직 로드되지 않았다면 상위 클래스 로더에게 책임을 위임한다.


Application ClassLoader > Extension ClassLoader > Bootstrap ClassLoader


최상단인 Bootstrap ClassLoader에서도 찾지 못했다면 다시 역순으로(Extension > Application) 로드를 요청하고 이렇게 한 바퀴를 돌아도 클래스를 찾지 못한다면 ClassNotFoundException, NoCladdDefFoundError가 발생한다.


1.1 Loading


1.1.1 Bootstrap ClassLoader


자바의 클래스는 Java.lang.ClassLoader 인스턴스에 의해 로드된다. 이 ClassLoader도 클래스이기 때문에 로드를 해줘야 하는데, 이 Bootstrap Class Loader가 담당한다. 주로 $JAVA_HOME/jre/lib 디렉토리에 있는 rt.jar 및 JDK 내부 클래스와 java.lang.Object를 로드한다.


1.1.2 Extension ClassLoader


Bootstrap Class Loader의 자식이며, 자바 표준 코어 클래스의 확장 클래스들을 로드하는 역할이다.


1.1.3 Application ClassLoader


말 그대로 애플리케이션 레벨의 클래스들을 로드하며, 우리가 작성한 소스 클래스들이 이 Application ClassLoader에 의해 로드된다.


1.2 Linking


1.2.1 Verify


바이트코드 검증기가 해당 바이트코드가 적절한지 아닌지 검증한다. 즉, .class 파일이 유효한지 검증하며, 만약 검증에 실패했을 경우 검증에 대해 에러가 발생한다.


1.2.2 Prepare


클래스가 필요로 하는 메모리를 할당하고, 클래스의 필드, 메서드, 인터페이스를 나타내는 데이터 구조를 준비한다.


1.2.3 Resolve


심볼릭 메모리 공간에 적재된 레퍼런스를 메서드 영역에 있는 실제 레퍼런스로 교체한다. new Hello() 로 객체 생성 시, 이 new Hello() 가 힙에 들어 있는 인스턴스를 가리키는 작업을 Resolve 에서 하게 된다.


심볼릭 메모리 공간에 적재된 레퍼런스??


실제 메모리의 주소를 참조하는 것이 아닌, 이름에 의한 참조를 의미한다. '바로 가기' 개념으로 이해하면 될 듯.


1.3 Initialization


링크 과정의 Prepare 단계에서 확보한 메모리 영역에 클래스의 static 값들을 할당한다.

2. Runtime Data Area

프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간이다.

image


2.1 Method Area


static 변수를 포함한 클래스 정보들(클래스명, 패키지 경로, 상속 클래스, 메서드, 변수)이 여기에 저장되고 클래스 정보를 처음 메모리 공간에 올릴 때, 초기화되는 대상을 저장하기 위한 메모리 공간이다. 즉, 이 공간은 공유되는 장소이다.


2.2 Heap Area


모든 객체와 해당 인스턴스 변수 및 배열이 이 곳에 저장된다. 메서드 및 힙 영역은 여러 스레드에 대해 메모리를 공유하므로 이 곳에 저장된 데이터는 스레드로부터 안전하지 않다.


2.3 Stack Area (Thread)


하나의 쓰레드 영역에 생기는 공간이며, 여기서 실행된 메서드들이 스택으로 차곡차곡 기록된다. 쉽게 말하면 예외가 발생했을 때 자주 볼 수 있는 콜 스택 구조라고 생각하면 될 것 같다.


2.4 PC Register (Thread)


쓰레드가 생성될 때 마다 생성되는 공간이다. 쓰레드가 어디를 어떻게 실행해야할지 기록하는 부분으로 현재 수행중인 JVM 명령의 주소를 갖게 된다.


2.5 Native Method Stacks (Thread)


컴파일 되어 생성되는 바이트 코드가 아닌 Native하게 작성된(C 코드, C++코드 등등..) 메서드를 실행시키는 영역이다. 쉽게 말해 바이트 코드는 Stack Area에, Native 메서드는 이 공간에 차곡차곡 기록된다.

3. Execution Engine

바이트코드가 Runtime Data Area에 적재되었을 때, 이 실행 엔진에서 실행된다.


3.1 Interpreter


실제 바이트 코드를 한줄씩 바이너리 코드로 컴파일한다. 하지만 하나의 메서드를 여러번 실행할 경우, 계속해서 한 줄씩 변환한다면 굉장히 비효율적인데, 이 비효율적인 방법을 JIT 컴파일러가 완화해준다.


3.2 JIT Compiler


인터프리터의 단점을 보완하기 위해 도입된 방식, 바이트 코드 전체를 컴파일하여 바이너리 코드로 변경하고, 이후에는 해당 메서드를 더 이상 인터프리팅 하지 않고, 바이너리 코드로 직접 실행한다. 방금 봤던 인터프리터가 한줄씩 읽어서 실행하는 방식이 아닌, 바이트 코드 전체가 컴파일된 바이너리 코드를 실행하기 때문에 전체 실행 속도는 인터프리터에 비해 빠르다.


3.3 Garbage Collector


더 이상 참조하지 않는 객체를 메모리 공간에서 해제하는 역할이다. 가비지 컬렉터는 따로 포스팅하여 정리해보자.


출처

반응형

'Language & Framework > JAVA' 카테고리의 다른 글

Garbage Collection 정리  (0) 2021.12.11