Study/java

[백기선님의 자바 라이브 스터디] 1주차 - JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.

에디개발자 2020. 12. 21. 07:00
반응형

www.youtube.com/watch?v=HLnMuEZpDwU

나를 닮았다고 한다...

목표

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

 

학습할 것

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

JVM이란 무엇인가?

Java Virtual Machine

영어를 그대로 해석하면 자바 가상머신입니다. 가상머신의 장점은 새로운 가상 환경을 띄워동작할 수 있기 때문에 OS에 상관없이 동작시킬 수 있습니다. 그러한 가상 환경을 이용하여 자바 바이트코드를 실행시킬 수 있는 환경을 제공해줍니다.

 

출처 : https://www.itworld.co.kr/news/110837

JVM이 없다면?

내가 생성한 파일을 컴파일하고 나온 바이트코드들이 OS마다 다릅니다. 이 말은 즉 Window에서 컴파일한 바이트코드들은 리눅스에서 정상작동을 하지 않습니다. 이 문제를 해결하기 위해 C나 C++은 Cross Complie 방식을 사용합니다. 내가 Window에서 컴파일하지만 리눅스에서 사용을 한다면 타겟을 리눅스로 잡고 컴파일하는 것입니다. 번거롭네요. 

이런 불편함을 JVM은 어떤 OS에서든 JVM만 가능하다면 동작하도록 도와줍니다. 

 

특성

OS에 종속되지 않고 실행가능하다.

그림과 같이 Application을 JVM이라는 Java 바이트코드를 실행시켜줄 가상 머신으로 실행시켜줍니다. 가상 머신인 만큼 OS에 종속되지 않고 어느 환경에서도 실행이 가능합니다.

Garbage Collection

JVM 내부에서 Garbage Collection이 작동하고 있습니다. 사용하지 않는 메모리( Garbage )를 수집 ( Collection ) 하여 해제해주는 역할을 합니다. 예를 들어 메서드에서 리스트를 선언하고 메서드가 종료되면 메모리에 올라가 있는 리스트를 찾아서 메모리를 해제합니다.

public void animals_test() {
    // 메모리에 할당
    List<String> animals = new ArrayList<String>();
    animals.add("고양이");
    animals.add("강아지");
    
    ...
}

// 메서드 종료 시 메모리에 할당되어있는 garbage를 수집하여 제거한다.
 개인적으로 C++을 경험해본 사람으로 정말 편리한 환경입니다.
C++에서 가장 찾기 어려운 버그가 메모리 에러였습니다. 어디에 선언해놓고 해제했는지 찾기 너무 힘들었습니다.
JVM은 알아서 해주니 정말 유용합니다. 

자바코드가 실행되기 까지의 과정

출저 : https://www.youtube.com/watch?v=UzaGOXKVhwU

자바코드는 그림과 같이 실행되어집니다. 먼저 Frontend, Backend로 나뉘어집니다. 

Frontend는 모든 JVM이 동일합니다. 하지만 Backend는 JVM의 종류마다 다릅니다. Window JVM, Linux JVM, Mac JVM 으로 모두 다르게 동작합니다. Frontend, Bankend의 자세한 내용은 밑에서 다루겠습니다.

컴파일하는 방법

먼저 우리가 Java Source를 작성합니다. 그리고 build라는 명령을 실행하면 Java Complier는 javac라는 명령어를 통해 Java Source 를 기계어인 Byte Code ( .class ) 파일로 변환해줍니다.

Store.java  ->  Store.class

 

실행하는 방법

java Store.class

위 명령어를 실행하면 ClassLoader가  Store.class ( byte code ) 파일을 실행엔진 ( Excution Engine )으로 가져옵니다. 실행엔진은 Class 파일을 해석되어 JVM 메모리( Runtime Data Area )에 올라갑니다.

 

JVM 메모리

JVM이 Java Byte Code를 실행하기 위한 메모리 공간이 있습니다. 이것을 Runtime Memory Area라고 합니다. 

출저 : https://www.youtube.com/watch?v=UzaGOXKVhwU

간단하게 보면 Runtime Data Areas의 메모리 종류는 그림과 같습니다. 

  • Method Area
    • Class Loader가 클래스 파일을 읽어오면 클래스 정보를 파싱해서 Method Area에 저장
    • 모든 Thread에서 공유
  • Heap
    • 프로그램을 실행하면서 생성한 모든 객체를 Heap에 저장
    • 모든 Thread에서 공유
  •  PC ( Program Counter )
    • 각 쓰레드는 메서드를 실행하고 있고 pc는 그 쓰레드안에서 몇 번째 줄을 실행해야하는지 역할
    • 모든 Thread에 각각 존재
  • Stack
    • 스택 프레임은 메서드가 호출될 때마다 생성됨.
    • 메서드 실행이 끝나면 pop되어서 Stack에서 제거됨
    • Thread별로 한개만 존재
  • Native Method Stack
    • Java Byte Code가 아닌 다른 언어로 작성된 메서드를 의미

바이트 코드란 무엇인가?

바이트 코드는 JVM에서 해석할 수 있는 언어입니다.

해석은 실행 엔진( Excution Engine )이 진행하여 Runtime Data  Area에 적재시켜놓습니다.

하드웨어에 종속되지 않고 가상 머신에서 돌아갈 수 있도록 도와주는 코드입니다.

 

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

JVM 내부의 실행엔진에는 Interpreter와 JIT Complier가 존재합니다.

먼저 Interpreter는 코드를 한 행씩 분석하여 기계어를 생성해줍니다. 하지만 한 행씩 분석하기 때문에 느리다는 단점이 존재합니다. 이러한 단점을 보완하기 위해 JIT Complier가 존재합니다.

JIT Complier는 기계어를 생성할 때 캐싱 기능을 활용하여 함수가 여러번 호출되어도 새롭게 생성하지 않고 기존에 생성된 기계어를 호출합니다. 

 

JIT Complier는 런타임에서 중간언어(byte code)를 번역하여 네이티브 기계어로 해석합니다. 

첫 번째 컴파일 후 다시 들어오는 처리에 대해서는 캐싱처리를 하여 빠르게 처리를 할 수 있습니다.

 

JVM 구성 요소

앞서 정리한 글을 정리하자면 아래 그림과 같습니다.

출저 : https://aljjabaegi.tistory.com/387

JVM은 Class Loader, Execution Engine, Runtime Data Area로 구성되어 있습니다.

  • Class Loader : .java 파일을 컴파일한 .class 파일을 JVM 내부로 로드하는 역할을 합니다.
  • Execution Engine : 로드된 .class 파일 ( byte code )를 해석하여 JVM 메모리에 배치시킵니다.
  • Runtime Data Area : JVM에서 byte code 파일을 처리하기 위한 메모리를 칭합니다.

 

JDK와 JRE의 차이

Java Runtime Enviroment
Java Development kit
  • JRE
    • 컴퍼일된 자바 프로그램을 실행 시킬 수 있는 자바 환경입니다. 자바 프로그램을 실행시키려면 반드시 필요합니다.
    • JRE 만으로 JVM의 모든 환경이 구현되있습니다.
    • Java의 프로그래밍 도구는 포함되어있지 않습니다.
  • JDK
    • 자바 프로그래밍 시 필요한 컴파일러 포함
    • JDK를 설치하면 JRE도 포함되어 있습니다.

결론으로 JVM은 JRE에 포함되있고 JRE는 JDK에 포함되있습니다.

JDK > JRE > JVM

출저 : https://goodgid.github.io/Java-JDK-JRE/

 

 

 

반응형