본문 바로가기

develop

1주차 과제: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.

🎯  목표

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

 

🖍  학습할 것

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

 

 


 

1. JVM이란 무엇인가

Java Virtual Machine의 약자로 바이트코드를 실행하는 주체이다.

 

- JVM의 특징은 무엇일까?

1) WORA (Write Once Run Anywhere)

 

한번 작성하면 어디서든 실행할 수 있다는 말이며 OS에 종속적이지 않고 자바 코드를 실행할 수 있다.

[사진 1]과 같이 윈도우, 리눅스 등 어느 OS에서 쓰는지와 상관없다. 즉, 바이트코드를 각 OS에 맞게 해석하여 실행한다.

 

[사진 1] 출처 : https://velog.io/@jaden_94/1%EC%A3%BC%EC%B0%A8-%ED%95%AD%ED%95%B4%EC%9D%BC%EC%A7%80

 

2) GC (Garbge Collection)

 

자바 이전의 모든 프로그램의 메모리는 프로그래머가 관리해야 했다. 하지만 자바에서는 JVM이 해준다.

Garbage Collection은 프로그램에서 더 이상 사용되지 않는 부분을 찾아 메모리에서 제거함으로써 메모리 관리를 하는 프로세스이다.

 

 

실행 흐름 : [1] .java 파일 작성 → [2] class 파일로 컴파일 → [3] class 파일을 JVM에서 실행

 

 

- 자바 프로그램을 바로 실행할 수는 없나?

컴퓨터가 이해할 수 있는 언어는 0과 1로 이루어진 바이너리 코드이다.

그렇기에 가상머신이 바이트코드를 먼저 해석해야 한다. 결론은 바로 실행할 수 없다.

 


 

2. 컴파일 하는 방법

컴파일하는 것은 .java 파일을 .class 파일(바이트코드)을 만든다는 것을 의미한다.

즉, 우리의 언어는 컴퓨터가 이해하지 못하므로 컴퓨터가 이해할 수 있도록 '통역'하는 작업이다.

 

JDK (Java Development Kit, 자바 개발 도구)를 설치하면 bin 폴더 안에 javac라는 java compiler가 포함되어 있다.

이를 사용해서 .class 파일을 만든다.

 

기본적으로 두 프로그램이 필요하다.

‣ javac.exe

‣ java.exe

 

javac.exe는 자바 소스코드를 컴파일할 때 사용하는 프로그램이며 컴파일된 바이트코드를 실행할 때 java.exe를 사용한다.

 

 

javac.exe는 JDK, java.exe 는 JRE에 포함되어 있기에 JDK과 JRE를 설치해야 하지만 과거와 다르게 요즘은 JDK에 JRE가 포함된 형태로 배포되고 있기에 JDK만 설치해도 무관하다.

 

 

구체적으로, 컴파일 하는 방법은

$  javac fileName.java

 

실행하는 방법은

$  java fileName

 

출처: https://www.guru99.com/java -virtual-machine-jvm.html#1

 

 

출처 :  https://t1.daumcdn.net/cfile/tistory/995DA63D5AE9701B34

 

 

•JDK : Java Development Kit로 자바 11부터는 JRE를 포함하고 있으며 개발에 필요한 여러 가지 툴을 제공한다.

 

•JRE : Java Runtime Environment로 바이트코드로 컴파일된 자바 프로그램을 실행할 때 사용한다.

 


 

3. 실행하는 방법

java.exe 파일을 사용하여 바이트코드로 컴파일된 .class 실행

 

$ java fileName

( 실행시에는 소스 파일명의 확장자는 붙이지 않음 )

 


 

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

우리가 만든 프로그램을 실행하는 것은 컴퓨터이다. 그렇기 때문에 프로그램은 컴퓨터가 이해할 수 있는 형태로 작성되어 있어야 한다.

자바로 작성한 .java 파일은 사람이 이해할 수 있는 언어로, 컴퓨터는 이해할 수 없다.

그래서 번역을 통해 컴퓨터가 이해할 수 있는 형태로 만들어줘야 한다.

이 작업은 JVM이 담당한다.

 

그래서 우리는 JVM이 이해할 수 있는 형태로 번역을 해서 줘야 한다.

JVM이 이해할 수 있는 형태가 바이트코드이다.

 

자바 컴파일러에 의해 변환되는 코드의 명령어의 크기가 1바이트라서 자바 바이트코드라고 불린다.

 

정리하자면, 프로세서가 이해하는 언어는 기계어

                  가상 머신이 이해하는 언어는 바이트코드이다. (소스파일을 컴파일하면 바이트코드가 된다)

 

 

 ➕ 바이너리 코드와 기계어

 

바이너리 코드란? 컴퓨터가 인식할 수 있는 0과 1로 구성된 이진 코드를 의미한다.

 

기계어란? 0과 1로 이루어진 바이너리 코드이다. But 모든 이진코드가 기계어인 것은 아니다. (바이너리 코드 != 기계어)

 


 

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

 

Just-In-Time의 약어로서 JRE(Java Runtime Environment)에 존재하면서 프로그램을 실행할 때 기계어로 번역해 전달하는 장치이다.

 

 

💡 왜 JIT가 쓰여야 할까?

 

자바 바이트 코드는 인터프리터 언어이다. 인터프리터가 한줄씩 읽고 해석하고, 그에 해당하는 기능을 실행시키는 인터프리터 언어이기에

기기에서 직접 돌아가는 기계어로 컴파일 되는 언어로 만든 실행 파일에 비해 실행 속도가 느리다.

 

따라서 속도를 개선하기 위해 같은 코드를 매번 새롭게 해석하는 대신, 실행 전에 미리 JIT 컴파일러를 이용해

"반복적인 코드"를 "네이티브 코드"로 전부 바꿔두고 그다음부터는 인터프리터가 컴파일된 네이티브 코드를 바로 사용해

인터프리터의 느린 실행 성능을 개선한다.

 

단점은 JIT 컴파일러가 컴파일하는 과정은 바이트 코드를 하나씩 인터프리팅하는 것보다 훨씬 오래 걸리므로

초기 실행 속도와 메모리 사용량에서 손해를 본다.

따라서, JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고,

일정 속도를 넘을 때만 컴파일을 수행한다.

 

출처 : https://aboullaite.me/understanding-jit-compiler-just-in-time-compiler/

 

 

 


 

6. JVM 구성 요소

먼저, JVM이 어느 위치에 속해있는지, 어느 것과 관련있는지 다시 한번 보자. 

 

출처 : the-java-code-manipulation(백기선님 자료)

 

 

JVM (Java Virtual Machine) - 자바 가상 머신으로 자바 바이트코드 (.class 파일)를 OS에 특화된 코드로

변환(인터프리터와 JIT 컴파일러)하여 실행한다.

 

JRE (Java Runtime Environment) - [JVM + 라이브러리]

Java application을 실행할 수 있도록 구성된 배포판이다.

개발 관련 도구는 포함하지 않는다. (JDK에서 제공)

 

JDK (Java Development Kit) - [JRE + 개발 툴]

 


 

JVM은 크게 3가지 구성 요소를 가진다. (사람마다 다르게 본다 - 4가지로 보는 의견도 있다)

  1.  Class Loader

  2.  Memory

  3.  Execution Engine

 

출처 : the-java-code-manipulation(백기선님 자료)

 

 

♦️ 클래스 로더 시스템

 

  JRE의 일부로 .class에서 바이트코드를 읽고 메모리에 저장한다.

  로딩 : 클래스를 읽어오는 과정

  링크 : 레퍼런스를 연결하는 과정

  초기화 : static 값들 초기화 및 변수에 할당

 

 

♦️ 메모리

 

  메모리 영역에는 클래스 수준의 정보 (클래스 이름, 부모 클래스 이름, 메소드, 변수) 저장, 공유 자원이다.

  힙 : 객체를 저장, 공유 자원이다.

  스택 : 쓰레드마다 런타임 스택을 만들고 그 안에 메소드 호출을 스택 프레임이라 부르는 블록으로 쌓는다.

  PC 레지스터 : 쓰레드마다 스레드 내 현재 실행할 스택 프레임을 가리키는 포인터가 생성된다.

 

 

♦️ 실행 엔진

 

  인터프리터 : 바이트코드를 한줄 씩 실행

  JIT 컴파일러 : 인터프리터 효율을 높이기 위해 인터프리터가 반복되는 코드를 발견하면 JIT 컴파일러로 반복되는 코드를

  모두 네이티브 코드로 바꿔둔다. 그 다음부터 인터프리터는 네이티브 코드로 컴파일된 코드를 바로 사용한다.

  GC : 더 이상 참조되지 않는 객체를 모아서 정리한다.

 

 

♦️ JNI (Java Native Interface)

 

  자바 애플리케이션에서 C, C++, 어셈블리로 작성된 함수를 사용할 수 있는 방법 제공

  Native 키워드를 사용한 메소드 호출

 

 

♦️ 네이티브 메소드 라이브러리

 

  C, C++로 작성된 라이브러리

 

 


❗️ 클래스 로더 자세히 ❗️

 

출처 : the-java-code-manipulation(백기선님 자료)

 

 

클래스 로더

  • 로딩, 링크, 초기화 순으로 진행된다.
  • 로딩 : 클래스 로더가 .class 파일을 읽고 그 내용에 따라 적절한 바이너리 데이터를 만들고 '메소드' 영역에 저장한다.

                 로딩이 끝나면 해당 클래스 타입의 Class 객체를 생성하여 '힙' 영역에 저장

  • 링크  : 세 단계로 나눠져 있다.

                - Verify : .class 파일 형식이 유효한지 체크한다.

                - Prepare : 클래스 변수와 기본값에 필요한 메모리

                - Resolve : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.

  • 초기화 : static 변수의 값을 할당한다.

 

7. JDK와 JRE의 차이

 

JDK (Java Development Kit) - 자바 개발 도구

JRE (Java Runtime Environment) - 자바 실행 환경

 

자바 언어로 프로그램을 개발하기 위해서는 JDK를 설치해야 하고

자바 언어로 작성된 프로그램을 실행하기 위해서는 JRE를 설치해야 한다.

 


 

 

github.com/whiteship/live-study/issues/1

 

1주차 과제: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가. · Issue #1 · whiteship/live-study

목표 자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기. 학습할 것 JVM이란 무엇인가 컴파일 하는 방법 실행하는 방법 바이트코드란 무엇인가 JIT 컴파일러란 무엇이며 어떻게 동작하는지 JV

github.com

 

 

 

'develop' 카테고리의 다른 글

3주차 과제: 연산자  (0) 2021.02.25
2주차 과제: 자바 데이터 타입, 변수 그리고 배열  (0) 2021.02.24
[java] What is 'split' ?  (0) 2021.02.12
[java] What is 'substring' ?  (0) 2021.02.11
난수 생성 (Random 클래스)  (0) 2021.02.10