본문 바로가기

JAVA/Spring-boot

[Java] 내가 짠 Java코드를 컴퓨터가 어떻게 읽을까? (feat. JIT compiler)

반응형

안녕하세요, 도토리입니다.

잘못된 정보가 있거나 오류가 있으면 언제든지 댓글로 이야기 해주세요!! 😅

 

과거에 저는 컴퓨터가 어떻게 읽어서 우리의 코드를 실행시킬까에 대해서 무지했었습니다..(부끄럽네용..ㅎㅎ)

그래서 제목처럼 내가 짠 Java 코드를 컴퓨터는 어떻게 읽을까?라는 단순한 질문에 제대로 대답을 못하는 저 자신을 발견하고 그 의문점을 토대로 JVM에 대해서 이해하고 공부한 과정입니다.

 

이후에 JVM에 대해서 사내 지식공유회때 공유한적이 있는데,

이때 자료를 만들어둔것을 바탕으로 몇차례 나눠서 블로그에 글을 정리해보겠습니다.

 

 컴퓨터는 어떤 언어를 읽어면서 구동되는걸까?

다들 많이 들어보시고 알고 계실겁니다.

컴퓨터는 자기가 읽을 수 있는 기계어(0과 1로 구성)를 읽어가면서 cpu에서 실행됩니다.

 

기계어 로드 -> 해독 -> 명령어 해석 -> 실행 -> 다음 명령어로 이동

위 순서를 프로그램이 메모리에 로드되고 cpu가 이를 실행할때 계속 반복되면서 프로그램이 종료되면 cpu는 실행을 멈춥니다.

 

이러한 과정으로 컴퓨터는 프로그램을 실행합니다..!

 

그러면 우리가 짜는 java 코드는 어떻게 읽는걸까요?!?

그걸 이해하려면 JVM에 대해서 이해가 필요합니다! 

 

 JVM이 나오게된 배경

JVM에 대해서는 뒤에 이야기를 하겠지만 저는 어떠한것을 이해할때, 이 기능 혹은 방법이 왜 나오게 되었는지 과거의 어떠한 부분때문에 이렇게 발전한것인지 아는것을 되게 좋아합니다.

그래서, JVM이 나오게된 배경을 먼저 설명드리고 JVM에 대해서 이야기를 풀어갈까 합니다.

 

Java가 나오기 전에 C나 C++에서는 고질적인(?) 아쉬운(?)점이 하나 있었습니다. 

바로 컴파일하는 환경과 배포하여 실행하는 환경의 OS가 같아야 하는 이슈였는데요...

 

왜냐하면 C나 C++은 컴파일 언어로 컴파일 할때, 바로 기계어로 변환하는 과정을 거쳤기 때문입니다.

물론, 기계어로 변환하는 과정에서 코드 최적화를 진행하기에 일반적으로 인터프리터 언어보다 더 빠른 성능을 가질 수 있습니다.

 

그래서 예를들어 linux에서 컴파일 하면 window 환경이나 unix 환경에서는 구동이 되지 않는 것입니다.

 

linux에서 Compile하면 linux 환경에서만 실행 가능

 

linux에서 Compile하면 window에서 실행 불가

 

이렇게 compile하는 OS에 종속적이다보니 이를 극복하기 위해서 Cross Compile을 지원하기 시작했습니다.

 

Cross Compile이란? 

컴파일러가 실행되는 OS가 아닌 다른 OS에서도 실행 가능하도록 할때 사용되는것입니다.

 

위의 예시에서 Linux 환경에서 compile 하였지만 구동되는 서버는 window라면 target server의 os를 염두하여 window에서 돌아갈 수 있도록 compile하는 것을 크로스 컴파일이라고 하는것입니다.

 

크로스 컴파일을 지원하지만.. 타겟서버의 os 별로 결국 또 컴파일하고 또 컴파일하고 이런 비효율이 계속 발생하다보니.. 

자바에서는 Build Once Run Everwhere 이라는 문구로 os 종속적인 문제를 해결하려고 했습니다!

 

 JVM이란?

Build Once Run Everywhere이라는 문구를 지키기 위해서는 JVM이 핵심인데요. 이제 JVM에 대해서 이야기를 해보겠습니다.

 

간단하게 한줄로 이야기하자면 JVM은 Java Virtual Machine으로 compile된 파일을 (.class 파일) 기계가 읽을 수 있도록 기계어로 변환해주는 가상 머신입니다.

(물론 GC, 메모리 관리 등 여러 다른 기능들이 있지만 이 글의 목적은 어떻게 컴퓨터가 자바 코드를 읽는가? 이기때문에 관련된것에만 초점을 맞추겠습니다.)

 

C와 C++같은 언어는 컴파일 언어로써, 소스코드를 컴파일러를 통해 기계어로 번역한 후에 실행합니다.

즉, 전체 코드가 먼저 컴파일되어 실행 파일로 변환된 다음에 실행되죠. 이로인해 실행시간이 짧고 번역할 필요가 없어 속도가 빠릅니다.

 

반면 자바는 인터프리터언어와 컴파일러 의 조합으로 생각하시면 됩니다.

자바는 우리가 작성하는 자바코드 (.java 파일)를 JVM이 인터프리터 역할을 하며 읽을 수 있도록 .class 파일로 변환해줍니다.

이때 사용되는 컴파일러가 javac 컴파일러 입니다.

 

javac로 컴파일되어 .class 파일을 생성해 내고, 이를 jvm에서 읽어서 인터프리터를 통해 실행하거나, JIT(Just-In-Time) 컴파일러를 통해 기계 코드로 컴파일하여 실행하는 과정을 거칩니다.

 

* JIT(Just-In-Time) Compiler란?

JIT compiler는 소스 코드를 먼저 바이트코드로 변환하고, 이를 인터프리터가 실행하는데, 반복적으로 같은 작업을 하면 효율이 떨어지기는 현상을 해결하기 위해 사용됩니다.

프로그램이 실행 중일 때, JIT 컴파일러는 반복적으로 실행되는 코드 블록을 식별하고, 이를 바이트코드(.class 파일)에서 네이티브 기계 코드(기계어)로 컴파일합니다. 이러한 기계어는 프로그램의 나머지 부분과 함께 실행됩니다.

한마디로 jit compiler는 똑같은 코드를 기계어로 변환해두는걸 캐싱해두는것이고 그때그때 바로(Just-In-Time) 변환해주는것으로 생각하시면 될 것 같습니다.

 

그래서 다시 한번 순서를 정리하자면 아래와 같다!

전반적인 내가 작성한 java 코드가 실행되는 과정

 

 마무리

JVM은 사실 이 것 외에도 많은 기능을 제공하고 있다.

GC도 담당하고, 적절한 메모리 할당, 또 stack 영역 heap 영역 등.. 많은 부분이 있지만..

초보자들이나 궁금하지만 누구에게 물어보기 부끄러워 하는 사람들을 위해서 한번 정리를 해보았다.

 

더 궁금하신점이나 이해가 안되는 부분 있으시면 언제든지 댓글로 이야기 부탁드리며,

혹시 제가 잘못 정리한 부분이 있다면 언제든지 피드백 부탁드립니다 ㅎㅎ

 

감사합니다~~

반응형