-
JVM (Java Virtual Machine) 의 구조JAVA/Java 2020. 2. 22. 17:43
JDK와 JRE 란?
JVM (Java Virtual Machine)
- 자바 가상 머신으로 자바 바이트 코드(. class 파일)를 OS에 특화된 코드로 변환(인터프리터와 JIT 컴파일러)하여 실행한다.
JRE (Java Runtime Environment): JVM + 라이브러리
- 자바 애플리케이션을 실행할 수 있도록 구성된 배포판
- JVM과 핵심 라이브러리 및 자바 런타임 환경에서 사용하는 프로퍼티 세팅이나 리소스 파일을 가지고 있다
- 개발 관련 도구는 포함하지 않는다. (그건 JDK에서 제공)
JDK (Java Development Kit): JRE + 개발 툴
- JRE + 개발에 필요할 툴
바이트코드란?
- 바이트코드(Bytecode, portable code, p-code)는 특정 하드웨어가 아닌 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법이다. 하드웨어가 아닌 소프트웨어에 의해 처리되기 때문에 보통 기계어 보다 더 추상적이다.
- JVM이 사용자가 작성한. java 소스 코드 파일을 운영체제에 실행 가능한 명령어 집합 파일로 컴파일하는 과정 중에서 필요한 코드
- JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미
- 자바 컴파일러에 의해 변환되는 코드의 명령어의 크기가 1byte라서 자바 바이트 코드라고 불림
- 자바 바이트 코드는 자바 가상 머신만 설치되어 있다면 어느 운영체제에서도 실행 가능
JVM 의 구조
- Jvm의 구조는 크게 클래스 로더 시스템, 메모리, 실행 엔진으로 나눌 수 있다
- 우선 자바 파일을 javac(씨) 명령어를 통해서 닷 클래스(. class) 파일에 자바 바이트코드로 된 파일이 나오게 된다.
- 이 자바 바이트코드를 읽어서 메모리에 저장하고 레퍼런스를 연결, 클래스에 있는 스테틱 한 값들을 초기화하는 것이 클래스 로더가 하는 일이다.
- 메모리에는 크게 힙 메소드메서드 스택 등이 있다. 메서드 영역에는 클래스 수준의(클래스 이름, 부모 클래스, 메서드, 변수 ) 정보를 저장하게 된다. 힙 영역에는 객체를 저장한다. 이런 메서드나 힙은 공유 자원이다.
- 스택이나 PC 네이티브 메소드 스택 등은 스레드에 국한되는 자원 스택 영역은 스레드마다 런타임 스택을 만들고 그 안에 메서드 호출을 블록으로 쌓게 된다.
- 그리고 실행엔진은 이 바이트 코드를 한 줄씩 컴파일하면서 네이티브 코드로 바꿔서 실행한다.
- 그리고 반복적인 코드는 jit 컴파일러(바이트 -> 네이티브)가 처리하게 된다.
- 실행 엔진에 GC(Garbage Collector): 더 이상 참조되지 않는 객체를 모아서 정리한다.
GC?
- Garbage Collector(GC)는 Heap 메모리 영역에 생성된 객체들 중에 참조되지 않은 객체들을 제거하는 역할을 한다.
- GC의 동작 시간은 일정하게 정해져 있지 않기 때문에 언제 객체를 정리할지는 알 수 없다.
- 즉 바로 참조가 없어지자마자 작동하는 것이 아니라는 것이다. 또한 GC를 수행하는 동안 GC Thread를 제외한 다른 모든 Thread는 일시정지상태가 된다.
- 특히, Full GC가 일어나는 수초 간 모든 Thread가 정지한다면 심각한 장애로 이어질 수 있다.
JIT 컴파일러란 무엇이며 어떻게 동작할까?
- JIT 컴파일 (just-in-time-compilation) 또는 동적 번역(dynamic translation)은 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법이다.
- 전통적인 입장에서 컴퓨터 프로그램을 만드는 방법은 두 가지가 있는데, 인터프리트 방식과 정적 컴파일 방식으로 나눌 수 있다.
- 이 중 인터프리트 방식은 실행 중 프로그래밍 언어를 읽어가면서 해당 기능에 대응하는 기계어 코드를 실행하며, 반면 정적 컴파일을 실행하기 전에 프로그램 코드를 기계어로 번역한다
- JIT 컴파일러는 두 가지의 방식을 혼합한 방식으로 생각할 수 있는데, 실행 시점에서 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱하여, 같은 함수가 여러 분 불릴 때 매번 기계어 코드를 생성하는 것을 방지한다.
- 최근에 자바 가상 머신과. NET, V8(node)에서는 JIT 컴파일을 지원한다. 즉, 자바 컴파일러가 자바 프로그램 코드를 바이트 코드로 변환한 다음, 실제 바이트 코드를 실행하는 시점에서 자바 가상 머신이 바이트 코드를 JIT 컴파일을 통해 기계어로 번역한다.
- 다른 컴파일 유형과는 달리, JIT 컴파일러의 주요 정의 특성은 프로그램이 시작되고 코드를 컴파일한 후에 JIT 컴파일러를 실행한다는 것이다.
HelloLeaguecat.java 소스 코드를 생성했다고 가정하자
-
HelloLeaguecat.java 소스 코드를 작성
-
javac.exe(Java 컴파일러)가 바이트 코드 (HelloLeaguecat.class)로 변환해준다.
-
그리고 JVM에서 각 운영체제에 맞는 기계어로 번역해 전달한다.
- 그림을 보면 JIT 컴파일러는 JRE 안에 존재한다. (JRE는 JDK에 포함되고 JVM안에도 JIT이 존재한다.)
- 즉, JIT 컴파일러는 같은 코드를 매번 해석하지 않고 실행할 때 컴파일을 하면서 해당 코드를 캐싱해버린다. 이후엔, 바뀐 부분만 컴파일하고 나머지는 캐싱된 코드를 사용한다. 인터프리터의 속도를 개선 가능하다.
- interpreter
자바 바이트 코드를 한 줄씩 실행, 여러 번 실행하는 환경에서는 다소 느림
- JIT Compiler
Interpreter의 단점을 보완, 전체 바이트 코드를 컴파일, 캐시 사용으로 한번 컴파일하면 다음에는 빠르게 수행
JIT 동작 방식
- java는 객체 지향 지향 접근 방식을 따른다, 결과적으로 클래스로, JVM에 의해 실행되는 byte code로 구성되게 된다.
-
런타임에서 JVM은 클래스 파일을 로드하고 각각 적절한 계산이 수행된다. 인터프리터 시 java 응용 프로그램이 느린 경향이 있다.
-
JIT 컴파일은 런타임에 바이트 코드를 원시 기계 코드로 컴파일시켜 Java 프로그램의 성능을 향상한다.
-
JIT 컴파일러는 메서드 호출 내내 활성화된다. 이때, 컴파일된 메서드의 경우 디렉트로 호출하게 되는데, 이론적으로 컴파일에 프로세서 시간이나 메모리 사용이 필요하지 않다면 native compiler와 java 컴파일러의 속도는 동일하다
'JAVA > Java' 카테고리의 다른 글
자바의 다형성 이란? (0) 2020.03.30 자바의 리플렉션 (0) 2020.03.28 자바의 추상 클래스와 인터페이스 (0) 2020.03.28 Gradle 과 Maven 차이? (0) 2020.01.10 String과 StringBuffer, StringBuilder 클래스 차이 (0) 2020.01.10