etc/Today, I Learned

JVM 구조와 JAVA의 동작 원리

yusung_ 2023. 1. 10. 15:00

# JDK

  • 자바 개발 환경으로 자바 어플리케이션을 개발하기 위해 필요한 도구를 제공한다.
  • 자바 언어를 바이트 코드로 컴파일 해주는 자바 컴파일러(javac), 자바 클래스 파일을 해석해주는 역 어셈블리어(javap) 등이 있다.

# JRE

  • JRE는 자바 실행 환경으로 JVM,자바 클래스 라이브러리, 기타 자바 어플리케이션 실행에 필요한 파일들을 포함한다.

# JVM

- JVM은 자바 가상 머신으로 자바 어플리케이션을 실행하는 가상 머신이다. 실제 컴퓨터로 부터 JAVA 어플리케이션 실행을 위한 메모리를 할당 받아 Runtime Data Area를 구성한다.

  • JVM은 인터프리터와 JIT 컴파일러를 통해 바이트 코드를 각 운영체제에 맞는 기계어로 해석시켜 실행시키고, 가비지 콜렉터를 통해 어플리케이션의 동적 메모리를 관리한다.

📌 Runtime Data Area

자바 가상 머신은 프로그램 실행 중 다양한 런타임 데이터 영역을 사용한다. 런타임 데이터 영역은 모든 스레드들이 공유하는 영역과 스레드 별 할당되는 영역으로 구분된다. JVM을 시작하면 Heap 영역과 Method 영역이 생성되며 해당 영역들은 모든 스레드들이 공유한다. 각 스레드가 시작 될 때마다 스레드마다 PC Register, Stack, Navtive Method Stack이 생성되며 스레드가 종료될 때 사라진다. 마지막으로 모든 스레드들이 실행되고 종료되면 JVM이 종료되면서 Heap 영역과 Method 영역도 사라진다.

JAVA의 동작 원리

📌 JAVA Execution Engine

  • 인터프리터 : 바이트코드 명령어를 하나씩 읽어서 해석하고 실행한다. 하나씩 해석하고 실행하기 때문에 바이트코드 하나하나의 해석은 빠른 대신 인터프리팅 결과의 실행은 느리다는 단점을 가지고 있다. 흔히 얘기하는 인터프리터 언어의 단점을 그대로 가지는 것이다. 즉, 바이트코드라는 '언어'는 기본적으로 인터프리터 방식으로 동작한다.

  • JIT(Just-In-Time) 컴파일러 : 인터프리터의 단점을 보완하기 위해 도입된 것이 JIT 컴파일러이다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 해당 메서드를 더 이상 인터프리팅하지 않고 네이티브 코드로 직접 실행하는 방식이다. 네이티브 코드를 실행하는 것이 하나씩 인터프리팅하는 것보다 빠르고, 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 계속 빠르게 수행되게 된다.

📌 Class Loader

클래스 로더는 클래스 파일의 바이트 코드를 읽어 런타임 데이터 영역으로 가져온다. 클래스 로더는 부트스트랩 클래스 로더, 플랫폼 클래스 로더, 시스템 클래스 로더 3가지로 구분된다. 클래스 로더는 계층 구조를 가지고 있으며 시스템 클래스 로더는 플랫폼 클래스 로더를 부모로 가지고, 플랫폼 클래스 로더는 부트스트랩 클래스 로더를 부모로 가진다.

📌 Loading, Linking, Initializing

JVM은 동적으로 로드, 링크, 초기화 과정을 진행한다. 로딩은 특정 이름을 가진 클래스 또는 인터페이스의 바이트 코드를 찾은 후 클래스 또는 인터페이스를 생성하는 과정이다. JAVA 어플리케이션의 동작은 JVM을 시작한 후 특정 클래스를 런타임 데이터 영역으로 로딩한 후 로딩,링크,초기화 과정을 거쳐 최종적으로 특정 클래스의 public static method void main(String []) 함수를 실행하는 것이다. 해당 과정을 실행하면서 연쇄적으로 다른 클래스들을 로딩,링크,초기화한다.

 

< 정리 >

  • JDK에 있는 자바 컴파일러를 통해 java 파일을 바이트 코드(class 파일)로 만들고, JRE에서 바이트 코드를 실행시키면 JVM이 시작되면서 JVM 위에서 바이트 코드가 기계어로 해석되어 실행된다.

  • JVM의 명세를 따르는 가상 머신은 모두 JVM이다. 대표적으로 Oracle의 Hotspot이 존재한다.

  • JVM의 런타임 데이터 영역에는 모든 스레드들이 공유하는 Heap, Method 영역, 각 스레드 마다 존재하는 Stack, PC Register, Native Method Stack이 존재한다.

  • HotSpot의 JAVA 실행 엔진은 일반적으로 한줄 씩 바이트 코드를 읽어 인터프리터를 통해 기계어로 번역하며 자주 사용되는 바이트 코드는 JIT 컴파일러를 통해 캐시에 미리 컴파일 하는 방식으로 실행 엔진을 최적화 시킨다.

  • 클래스 로더에는 BootStrap, Platform, System 클래스 로더가 존재하며 각 클래스 로더들은 위임 모델과 계층 구조를 지닌다.

  • JVM은 동적으로 로딩,링크,초기화 과정을 진행하며 java 어플리케이션의 실행은 특정 클래스를 로딩, 링크, 초기화 과정을 거친 후 해당 클래스의 main method를 실행하는 것을 의미한다.

'etc > Today, I Learned' 카테고리의 다른 글

캐시(Cache)와 쿠키(Cookie)  (0) 2023.03.03
싱글톤(Singleton) 패턴이란?  (0) 2023.01.10
스택(Stack) & 큐(Queue)  (0) 2023.01.05
DI & IoC  (0) 2023.01.04
@Transactional  (0) 2022.12.14