[JAVA] JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가. #1

1

이 포스팅은 백기선님이 2020년 11월 진행하신 라이브 스터디과정을 토대로 작성되었습니다. 아래 URL에 들어가시면 다른 분들이 정리하신(그리고 제가 참고한) 자료들이 올라와 있습니다.
https://github.com/whiteship/live-study/issues/1

==========================================================

목표

자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기.

학습할 것

  1. JVM이란 무엇인가
  2. 컴파일 하는 방법/ 실행하는 방법
  3. 바이트코드란 무엇인가
  4. JIT 컴파일러란 무엇이며 어떻게 동작하는지
  5. JVM 구성 요소
  6. JDK와 JRE의 차이

==========================================================

1. JVM이란 무엇인가

  • JVM: Java Virtual Machine의 약자
  • Linux, Mac, Windows 등 서로 다른 OS에 맞게 java byte code를 해석해주는 역할

자바 소스파일(.java)를 JVM으로 실행하는 과정

1) java compiler(javac.exe)가 .java파일을 .class파일(java byte code)로 변환
-> byte code는 기계어가 아니어서 os에서 바로 실행되지 않음
2) byte code를 os가 이해할 수 있도록 jvm이 해석해줌
-> 이 해석과정때문에 jvm이 속도가 느렸지만, JIT(just in time) 컴파일러 구현을 통해 이를 극복
3) byte code는 jvm 위에서 os 상관없이 실행됨
-> os에 종속적이지 않고 디바이스에 상관없이 java파일이 jvm위에서 실행된다
-> java의 가장 큰 장점
4) jvm의 구성 컴포넌트 4가지
- Class Loader
- Runtime Data Areas(메모리)
- Execution Engine(실행 엔진)
- Garbage Collecor

2. 컴파일 하는 방법/ 실행하는 방법

java 컴파일 과정

1) 개발자들이 ide나 terminal환경에서 .java파일을 생성한다.
2) 그 후 build작업을 통해 java compiler(javac.exe)가 .class파일을 생성한다.
3) .class파일은 클래스 로더에 의해 JVM 내로 로드되고, 실행엔진에 의해 기계어로 해석되어 메모리상(Runtime Data Area)에 배치된다.
- 실행엔진의 종류: 인터프리터, JIT Compiler
- 인터프리터
바이트코드를 한 줄씩 읽어 실행이 느림
- JIT Compiler
인터프리터의 단점을 보완, 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일 한 후 더이상 인터프리팅 하지 않고 해당 코드 직접 실행
캐시 사용으로 한 번 컴파일하면 다음에는 빠르게 수행

3. 바이트코드란 무엇인가

  • 특정 하드웨어가 아닌, 가상컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법
  • 하드웨어가 아닌 소프트웨어에서 처리되기 때문에 보통 기계어보다 더 추상적
  • java의 경우 사용자가 작성한 .java 소스코드 파일을 JVM에서 운영체제에 실행 가능한 명령어 집합 파일로 컴파일하는 과정 중에 필요한 코드
  • JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미
  • 자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1byte라서 자바 바이트코드라고 불림

4. JIT 컴파일러란 무엇이며 어떻게 동작하는지

JIT 컴파일러

  • Just In Time의 약자
  • 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법
  • 컴퓨터 프로그램을 만드는 전통적인 방식(인터프리트 방식, 컴파일 방식) 두 가지를 혼합
  • JVM, .NET, V8(node.js)에서 JIT 컴파일 지원
  • 바이트코드를 읽어 빠른 속도로 기계어를 생성함

동작방법


출처: https://miro.medium.com/max/1400/1*VFo0CC-chzvqJk6sls6ukQ.png

  • JIT 컴파일러는 JRE안에 존재함
  • 같은 코드를 매번 해석하지 않고, 실행할 때 컴파일을 하면서 해당 코드를 캐싱함
  • 이후엔 바뀐 부분만 컴파일하고 나머지는 캐싱된 코드를 사용
  • 이러한 방식으로 인터프리터의 속도를 개선 가능

5. JVM 구성 요소

jvm의 구성 컴포넌트 4가지

  • Class Loader
  • Runtime Data Areas(메모리)
  • Execution Engine(실행 엔진)
  • Garbage Collecor


출처: https://www.guru99.com/images/1/2.png

Class Loader

  • 컴파일 결과로 만들어진 .class 바이트코드 파일을 읽어들여 메모리에 배치한다.
  • 로딩, 링크, 초기화 세 가지 과정을 거친다.

Runtime Data Areas(메모리)

  • JVM이 프로그램을 수행하기 위해 운영체제로부터 할당 받는 메모리 영역
  • 각각의 목적에 따라 5개 영역으로 나뉨
  • Method Area: 메타데이터, 상수 런타임 풀, 메서드에 대한 코드와 같은 클래스 구조를 저장하며, 공유자원(다른 스레드에서도 활용 가능)이다.
  • Heap: 모든 개체, 관련 인스턴스 변수 및 배열 저장
  • JVM Language Stacks: 로컬변수를 저장하고 부분적인 결과를 얻음
  • PC Registers: 현재 실행중인 Java 가상시스템 명령의 주소를 저장
  • Native Method Stack: 네이티브 라이브러리에 따라 네이티브 코드 명령을 보관

Execution Engine(실행 엔진)

  • Class Loader에 의해 JVM으로 Load된 Class파일(바이트코드)들은 Runtime Data Areas의 Method Area에 배치됨
  • JVM은 Method Area에 배치된 바이트코드를 Execution Engine에 제공하여 Class에 정의된 내용대로 바이트 코드를 실행시킴
  • Execution Engine은 Load된 바이트코드를 실행하는 Runtime Module

Garbage Collector

  • 더이상 사용되지 않는 인스턴스를 찾아 메모리에서 삭제
  • GC가 있기 때문에 java개발자들은 프로그램코드에서 메모리를 명시적으로 삭제할 필요가 없음

6. JDK와 JRE의 차이


출처 : https://www.inflearn.com/course/the-java-code-manipulation

  • JDK = JRE + a(개발에 필요한 도구)

JDK(Java Development Kit)

  • JAVA로 된 언어를 컴파일하고 개발할 수 있도록 햊는 개발환경 세트
  • JRE에서 개발을 위해 필요한 도구(javac, java, visualVM 등)을 포함

JRE(Java Runtime Environment)

  • JAVA를 개발할 필요는 없지만 실행은 시켜야 하는 경우 꼭 있어야 함
  • JVM이 자바 프로그램을 동작시킬 때 필요한 라이브러리 파일들과 기타 파일들을 포함하고 있음

1개의 댓글

comment-user-thumbnail
2021년 6월 27일

잘 봤습니다~

답글 달기