Repository navigation
Open
Description
JVM 이란?
- 개발자가 자바 소스 파일(xx.java)을 작성하고 컴파일하여($javac xx.java) 생성해놓은 바이트 코드(xx.class)를, 컴퓨터가 이해할 수 있는 기계어 코드로 변환하여 자바 프로그램을 실행시키는 소프트웨어
JVM이 왜 필요한가?
[JVM 실행 과정] 어떻게 중간역할을 할까?
JVM의 기본 2가지 기능
- 자바 프로그램이 어느기기, 어느 OS 상에서 실행될 수 있게 하는 것
- 프로그램 메모리를 관리하고 최적화 하는 것
JVM의 구성요소
- JVM은 크게 3가지 영역으로 나뉜다.
- Class Loader
- JVM Memory Area(=Runtime Data Area)
- Execution Engine
- Class Loader는 컴파일된 자바 바이트 코드를 JVM Memory Area에 로드하고, 그렇게 로드 된 자바 바이트 코드를 Execution Engine이 해석하여 실행시키다.
JVM의 구성요소 1. Class Loader
- 자바 프로그램이 실행될 떄 가장 먼저 동작하는 요소이다.
- 자바는 동적 로드(= 컴파일 타임이 아니라 런타임에 클래스를 처음으로 참조할 때 해당 클래스를 로드하고 링크되는 것)를 담당하는 부분을 말한다.
JVM의 구성요소 2. JVM Memory Area(=Runtime Data Area)
- JVM Memory Area은 크게 2가지로 분류 할 수 있다.
- 모드 스레드가 공유해서 사용하는 Method Area, Heap Area가 있고,
- 각 스레드마다 하나씩 생성하는 Stack, PC Register, Native Method Stack이 있다.
1-1. Method Area
- JVM이 시작될 떄 생성되는 공간으로, 바이트 코드가 이 영역에 저장된다.
- 클래스 정보, 변수 정보, static으로 선언한 변수가 저장된다.
- 클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 각종 필드 정보들과 메서드 정보, 데이터 Type 정보, Constant Pool, static변수, final class 등이 생성되는 영역
1-2. Heap (주기적으로 GC가 제거하는 영역)
- new 키워드로 동적으로 생성된 객체와 배열가 저장된다.
- Heap Area는 효율적인 GC를 위해 위와 같이 크게 3가지의 영역으로 나뉘게 됩니다.
- Young Generation 영역 : 젊은 객체들이 존재 -> 자바 객체가 생성되자마자 저장되는 곳
- Tenured Generation 영역 : 늙은 객체들이 존재
- Permanent Generation 영역 : 클래스나 메소드에 대한 정보가 존재
- Minor GC 또는 Young GC
- Heap 영역에 객체가 생성되면 최초로 Eden 영역에 할당이 된다. 이 영역에 데이터가 어느 정도 쌓이면 참조정도에 따라 Survivor의 빈공간으로 이동되고 회수 된다. 이렇게 Young Genration(Eden+Survivor)영역이 차게 되면 또 참조 정도에 따라 Old 영역으로 이동되거나 회수되는데, 이 GC를 말한다.
- Major GC 또는 Full GC
- Old 영역에 할당된 메모리가 허용치를 넘게 되면, Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 GC가 실행된다. 시간이 오래 걸리는 작업이고, 이떄 GC를 실행하는 쓰레드를 제외한 모든 스레드는 작업을 멈추게 된다. 이를 'Stop-the-world'라고 한다. 이렇게 Stop-the-world 가 발생하고 Old 영역의 메모리를 회수하는 GC를 말한다.
2-1. Stack
- 지역변수, 메서드의 메개변수, 메서드의 리턴 값, 임시적으로 사용되는 변수, 메서드의 정보가 저장된다.
2-2. PC Register
- Thread가 생성될 때마다 생성되는 영역으로 프로그램 카운터, 즉 현재 스레드가 실행되는 JVM의 주소와 명령을 저장하고 있는 영역이다.
- 즉, Thread가 어떤 부분을 어떤 명령어로 수행할지를 저장하는 공간이다.
2-3. Native Method Stack
- 자바가 아닌 다른 언어로 작성되 코드를 위한 공간이다.
- JNI(Java Native Interface)를 통해 호출하는 C/C++ 등의 코드를 수행하기 위한 공간이다.
JVM의 구성요소 3. Execution Engine
- Execution Engine은 크게 2분류로 구성되어 있는데, 바이트 코드를 기계어로 변환하는 Interpreter, JIT Compiler와 프로그램 메모리를 관리하는 GC로 구성되어 있다.
- 먼저, 바이트코드를 기계어로 변환하는 애들부터 살펴보자.
- 원래 JVM에서는 인터프린터 방식만 사용하고 있었다. 그런데, 성능 이유가 발생해서 JIT 컴파일러를 추가해서 이를 보완했다.
- 현재 JVM은 Interpreter 방식과 JIT 컴파일 방식 두 가지 방식을 혼합하여 사용한다.
- JIT 컴파일 방식은 비용이 소요되므로, JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고, 인터프리터 방식을 사용하다가 일정 기준이 넘어가면 JIT 컴파일 방식으로 명령어를 실행한다.
1. Interpreter
- 바이트코드 명령어를 하나씩 읽어서 해석하고 실행한다. 하나씩 해석하고 실행하기 때문에 바이트코드 하나하나의 해석은 빠른 대신 인터프리팅 결과의 실행은 느리다는 단점을 가지고 있다.
2. JIT Compiler
- 인터프리터의 단점을 보완하기 위해 도입된 것이 JIT 컴파일러이다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 해당 메서드를 더 이상 인터프리팅하지 않고 네이티브 코드로 직접 실행하는 방식이다. 네이티브 코드를 실행하는 것이 하나씩 인터프리팅하는 것보다 빠르다.
- 또한, JIT 컴파일러는 같은 코드를 매번 해석하지 않고, 실행할 때 컴파일을 하면서 해당 코드를 캐싱한다. 따라서, 이후에는 바뀐 부분만 컴파일하고, 나머지는 캐싱된 코드를 사용한다. 이렇게 JIT 컴파일러는 운영체제에 맞게 바이트 실행 코드로 한 번에 변환하여 실행하기 때문에 이전의 자바 해석기(Java interpreter) 방식보다 성능이 10배 ~ 20배 정도 더 좋다.
3. GC
Reference
Metadata
Metadata
Assignees
Labels
No labels
Activity
daadaadaah commentedon Feb 8, 2023

- https://www.youtube.com/watch?v=AWXPnMDZ9I0&ab_channel=%EC%9D%B4%EC%A0%95%EB%A1%9D