본문 바로가기
Back-end/Java_T.I.L

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

by 사장님나빠여 2021. 12. 28.

목표

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


# JVM이란 무엇인가

자바 가상 머신(JVM, Java Virtual Machine)이란 자바 바이트 코드를 실행시키기 위한 가상의 기계

자바 가상머신은 자바 바이트코드를 실행할 수 있는 주체이다. 일반적으로 인터프리터나 JIT 컴파일 방식으로 다른 컴퓨터 위에서 바이트코드를 실행할 수 있도록 구현되거나 jop자바 프로세서처럼 하드웨어와 소프트웨어를 혼잡해 구현하는

경우도 있다. (이론적으로는 100%하드웨어 구현도 가능하나 비효율적이다) 자바 바이트코드는 플랫폼에 독립적이며 모든 자바 가상 머신은 자바 가상 머신 규격에 정의된 대로 자바 바이트 코드를 실행한다. 따라서 표준 자바 API까지 동일한 동작을 하도록 구현한 상태에서는 이론적으로 모든 자바 프로그램은 CPU나 운영 체제의 종류와 무관하게 동일하게 동작할 것을 보장한다.

 

정의

- 기술적 정의: JVM은 코드를 실행하고 해당 코드에 대해 런타임 환경을 제공하는 소프트웨어 프로그램에 대한 사양(Specification)이다.
- 일반적 정의: JVM은 자바 프로그램을 실행하는 방법이다. JVM의 설정을 구성한 다음 설정사항에 따라 실행 중에 프로그램 리소스를 관리한다.

 

특징

 -스택 기반의 가상머신

 -단일 상속 형태의 객체 지향 프로그래밍을 가상 머신 수준에서 구현

 -포인터를 지원하되 C와 같이 주소 값을 임의로 조작이 가능한 포인터 연산이 불가능

 -가비지 컬렉션 사용

 -모든 기본 타입의 정의를 명확히 함으로써 플랫폼 독립성 보장

 -데이터 흐름 분석(data flow analysis)에 기반한 자바 바이트코드 검증기를 통해 스택 넘침, 명령어 피연산자의 타입 규칙 위반, 필

  드 접근 규칙 위반, 지역 변수의 초기화 전 사용 등 많은 문제를 실행 전에 검증하여 실행 시 안전을 보장하고 별도의 부담을 줄여줌

 -명령어에서 스택을 가져올 피연산자의 타입을 명령어에 지정(예:정수 덧셈은 iadd, 단정밀도 실수 덧셈은 fadd)

 

역할

바이트 코드로 변환된 코드를 클래스 로더가 JVM의 메모리에 올리면 JVM의 실행엔진인 인프리터나 JIT컴파일러가 해석하고 실행

jvm은 다른 프로그램을 실행시키는 것이 목적

  1. 자바 프로그램이 어느 기기나 운영체제 상에서도 실행될 수 있도록 한다.

  2. 프로그램 메모리를 관리하고 최적화 한다.

 


# 컴파일 하는 방법

컴파일이란? 

 -컴퓨터에게 일을 시키기 위해 사람의 말을 컴퓨터가 알아듣게 번역하는 것

 -사람은 한국어, 영어 등 자연어를 사용하지만 컴퓨터는 기계어만 이해할 수 있다.

 -자바에서의 컴파일은 자바 언어로 된 코드를 JVM이 인식 할 수 있는 JVM 명령어 코드(바이트 코드)로 변환하는 것을 의미한다.

 -대표적으로 JIT컴파일러가 하는 컴파일은 바이트 코드를 변환하는 것이 아니라 바이트 코드를 네이티브 코드로 변환하는 것을 의미한다.

 

자바 소스 코드 파일(.java) -> javac 컴파일러 -> JVM 바이트코드(.class)

JVM 컴파일 이미지

1.자바코드(.java)

  ex) public class Main{

          public static void main(String[] args){

              System.out.println("Hello, World!");

          }

      }

2. 컴파일러(Compiler)

  Java파일을 JVM(Java Virtual Machine)이 이해할 수 있는 자바 바이트 코드로 변환

 

3. 자바 바이트 코드(.class)

  JVM(Java Virtual Machine)이 이해할 수 있는 언어로 변환된 자바 소스 코드를 말한다.

  바이트 코드의 확장자는 .class이며, JVM이 설치되어 있으면 어느 운영체제에서도 실행이 가능하다.

 

4. 인터프리터(Interpreter)

  인터프리터란 ?

  원시 언어의 명령을 번역하면서 실행하는 프로그램.

  JVM(Java Virtual Machine) 안에 있는 인터프리터가 바이트코드를 한 줄씩 읽어서 프로그램을 실행한다.

 

javac.exe

- 자바 컴파일러 : 자바 소스코드를 바이트코드로 컴파일

java.exe

- 자바 인터프리터 : 컴파일러로 생성된 바이트코드를 해석하고 실행

javap.exe

- 역 어셈블러 : 컴파일된 클래스파일을 원래의 소스로 변환

jar.exe

- 압축 : 자바프로젝트를 실행시키기 위한 파일들을 압축

javadoc.exe

- 문서화 : 자바파일에 있는 주석들을 문서화

# 실행하는 방법

1. 자바 컴파일러를 통해 (.java) 파일을 자바 바이트코드 (.class)로 변환한다.

2. 클래스로더를 통해 자바 바이트코드를 런타임 데이터 영역에 로드한다.

3. 실행엔진을 통해서 실행한다.


# 바이트코드란 무엇인가

바이트코드(Java bytecode)란?

특정 하드웨어가 아닌 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법이다.

하드웨어가 아닌 소프트웨어에 의해 처리되기 때문에, 보통 기계어 보다 더 추상적이다.

역사적으로 바이트코드는 대부분의 명령 집합이 0개 이상의 매개 변수를 갖는 1바이트 크기의 명령 코드(opcode)였기 때문에

바이트 코드라 불리게 되었다. 바이트코드는 특정 하드웨어에 대한 의존성을 줄이고, 인터프리팅도 쉬운 결과물을 생성하고자

하는 프로그래밍 언어에 의해, 출력 코드의 한 형태로 사용된다. 컴파일되어 만들어진 바이트코드는 특정 하드웨어의

기계 코드를 만드는 컴파일러의 입력으로 사용되거나, 가상 컴퓨터에서 바로 실행된다.

자바 바이트코드란(Java Bytecode)?

자바 가상 머신이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미한다.

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

이러한 자바 바이트 코드의 확장자는 .class 이다.

자바 바이트 코드는 자바 가상 머신(Java Virtual Machine. JVM)만 설치되어 있으면, 어떤 운영체제에서라도 실행될 수 있다.


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

JIT(Just In Time) 컴파일러란?

프로그램이 실행 중인 런타임에 실제 기계어로 변환해 주는 컴파일러를 의미한다.

동적 번역(dynamic translation)이라고도 불리는 이 기법은 프로그램의 실행 속도를 향상시키기 위해 개발되었다.

즉, JIT 컴파일러는 자바 컴파일러가 생성한 자바 바이트 코드를 런타임에 바로 기계어로 변환하는 데 사용한다.

 

JIT컴파일러 동작원리

JIT 컴파일러는 자바에 기본적으로 설정되어 있는 기능이다. 메서드가 컴파일 되면 JVM은 해석되지 않고 직접 컴파일 메서드를 호출한다. 이론적으로 컴파일이 프로세서 시간과 메모리 사용을 필요로 하지 않는다면 모든 메서드를 컴파일 했을 때 Java 프로그램의 속도가 네이티브 프로그램의 속도에 가까워 질 수 있다. JVM이 처음 시작되면 수천 가지 메서드가 호출된다. 이렇게 모든 메서드를 컴파일하면 결국 프로그램이 매우 우수한 최대 성능을 달성하더라도 시작 시간에 상당한 영향을 줄 수 있다. 각 메서드에 대해 JVM은 사전 정의 된 컴파일 임계 값에서 시작하여 메서드가 호출 될 때마다 감소되는 호출 계수를 정의한다. 호출 계수가 0에 도달하면 메서드에 대한 Just In Time 컴파일이 시작도니다. 따라서 자주 사용되는 메서드는 JVM이 시작된 직후에 컴파일되며 사용되지 않는 메서드는 훨씬 나중에 컴파일되거나 전혀 컴파일되지 않는다. JIT컴파일 임계 값은 JVM이 빨리 시작하고 성능이 향상되도록 도와준다. 임계 값은 시작 시간과 장기능 성능 사이의 최적의 균형을 얻기 위해 선택되었다.

 


# JVM 구성 요소

  1. 클래스 로더(class loader)

   JVM내로 클래스를 로드하고 링크를 통해 배치하는 작업을 수행하는 모듈. 클래스 로딩, 링크, 초기화 순으로 진행

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

     -클래스 로더가 .class파일을 읽고, 내용에 맞는 binary데이터를 생성한 뒤 메모리의 Method영역에 저장한다(Meta Space)

      -로딩이 끝나면, 해당 클래스 타입의 class 객체를 생성해서 Heap영역에 저장한다.  

    ② 링크 : 레퍼런스 연결 과정 

      -Verify(검증) : .class형식 파일이 유효한지 확인. 바이트코드가 조작될 경우 JVM에러 발생

      -Prepare(준비) : 메모리 준비 과정. 클래스의 static변수, 기본값에 필요한 메모리를 준비

      -Resolve(해결) : Symbolic Memory Reference를 실제 Reference로 교체 (Optional 과정)

    ③ 초기화 : STATIC 값 초기화 하고 변수 할당하는 과정

 

2. Runtime Data Area

프로그램 수행을 위해 OS에서 할당받은 공간. PC레지스터, 스택, 네이티브 메서드 스택은 스레드마다 하나씩 생성되고

힙, 메서드 영역은 모든 스레드가 공유해서 사용

-스레드 마다 생성되는 것

① PC Register : 현재 수행중인 JVM 명령의 주소를 갖는다. 어떤 부분을 어떤 명령으로 실행할지를 기록하며 현재 명령과 주소를 저장한다

② Stack : 메서드 호출 시 생성되는 스레드 수행 정보를 기록. 임시 데이터를 저장한다

 ③Native Method Stack : 자바 외의 언어로 작성된 네이티브 코드를 위한 스택. JNI(Java Native Interface)를 통해 호출하는 코드를 수행하기 위함

 

-모든 스레드가 공유하는

①Heap : 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 메모리 영역

                    New연산을 통해 생성한 객채, 인스턴스를 저장하는 공간으로 가비지 컬렉션 대상

②Method Area : 클래스, 인터페이스, 필드, 메서드, Static변수, 바이트코드 등을 보관

 

3.Execution Engine

① 자바 인터프리터(interpreter)

인터프리터 원리

   인터프리터는 번역해야 할 파일을 받아 한 줄씩 실행시킨다

 

② JIT 컴파일러(Just-In-Time compiler)

 

③가비지 컬렉터(garbage collector)

프로그램을 개발하다 보면 유효하지 않은 메모리인 가비지(Garbage)가 발생하게 된다. C언어를 이용하면  free()라는 함수를 통해 직접 메모리를 해제

해주어야 한다. 하지만 Java나 Kotlin을 이용해 개발을 하다 보면 개발자가 메모리를 직접 해제해주는 일이 없다.

 이유는 JVM의 가비지 컬렉터가 불필요한 메모리를 알아서 정리해주기 때문이다. 대신 Java에서 명시적으로 붎리요한 데이터를 표현하기 위해서 일반적으로 null을 선언해준다.


# JDK와 JRE의 차이  

JDK는 JRE를 포함하고 있다!

JDK(Java Develpment Kit) 개념

  -JDK는 개발을 위해 필요한 도구(javac, java등)들을 포함한다

  -JDK를 설치하면 JRE도 같이 설치가 된다

  -JDK = JRE+ @

  -컴파일러, 디버깅 툴, 개발툴 등

 

JRE(Java Runtime Environment) 개념

  -JRE는 JVM이 자바 프로그램을 동작시킬 때 필요한 라이브러리의 파일들과 기타 파일이 있는 디렉토리

  -JRE는 JVM의 실행 환경을 구현했다고 할 수 있다

  -자바 프로그램을 실행시키기 위해선 JRE를 반드시 설치해야 한다

  -자바 프로그래밍 도구는 포함되어 있지 않기 때문에 자바 프로그래밍을 하기 위해선 JDK가 필요하다

  -라이브러리 각종파일

 

'Back-end > Java_T.I.L' 카테고리의 다른 글

5. 클래스  (2) 2022.01.02
4. 제어문_반복문(for, while, do-while)  (0) 2021.12.31
4. 제어문_선택문(if, else-if, switch)  (0) 2021.12.31
3. 연산자  (0) 2021.12.30
2. 자바 데이터 타입, 변수 그리고 배열  (0) 2021.12.29

댓글