ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스터디 1주차] JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가
    프로그래밍 언어/JAVA 2021. 5. 19. 17:28
    더보기

    오늘의 목표: 자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기

    1. JVM이란 무엇인가

    JVM은 Java Virtual Machine의 약어로 한국말로 번역하면 자바 가상 기계이다.

    단어의 뜻대로만 해석해 본다면 자바로 무언가를 하는 가상의 기계라고 보인다.

    자바는 프로그래밍 언어의 하나인 것은 알고 있고 그렇다면 자바로 무엇을 하는지, 왜 가상의 기계인지를 알면 JVM을 이해할 수 있다.

     

    먼저, JVM을 자세하게 알아보기 전에 java로 만들어진 프로그램에 대해 알 필요가 있다.

    (프로그램이란 컴퓨터에서 특정 목적을 수행하기 위해 프로그래밍 언어로 작성된 소스를 기계어로 번역한 것)

    java로 만들어진 프로그램은 운영체제가 바로 실행시킬 수 없는데 그 이유는 자바 프로그램은 완전한 기계어가 아닌,

    중간 단계의 바이트 코드이기 때문이다.

    (바이트 코드에 대한 설명은 뒤에서 자세히 하도록 하겠다.)

    그렇다면 내가 쓰고 있는 컴퓨터의 운영체제(윈도우나 MAC 등)가 java로 만들어진 프로그램을 실행시킬 수 없다는 것인데 이러한 역할을 해줄 무언가가 필요하다는 의미이다.

     

    이 역할 (바이트 코드를 해석하고 프로그램을 실행시키는 일)을 해주는 것이 JVM이다.

    여기서 원래는 프로그램을 실행시키는 일은 운영체제가 하는 것이지만, java 프로그램은 JVM이 마치 가상의 운영체제처럼 일을 도맡아 하므로 Virtual Machine이라고 불린 이유가 아닐까 싶다.

     

    이제 JVM이 무엇인지는 조금 알 것같다. java프로그램이 바이트 코드이기 때문에 이것을 운영체제 대신 해석하고 실행시켜주는 가상의 운영체제와 같은 역할을 하는 것.

     

    여기서 조금 더 JVM에 대해 알아보자면 JVM은 운영체제에 종속적이다.

    종속적이라는 말은 운영체제에 따라 JVM의 모습이 바뀌어야 한다는 것이고 윈도우용 JVM과 MAC용 JVM이 따로 존재해야한다는 것이다.

    왜 이렇게 따로 존재해야 할까?

    자바의 가장 큰 장점 중인 하나인 Write once, run anywhere.(한 번 작성하면 어디서든 실행된다.)라는 말이 있다.

    이 말은 운영체제별로 자바 프로그램을 별도로 개발되는 것이 아니라 하나의 자바 프로그램으로 개발되면 운영체제와 상관없이 실행이 된다는 것이다.

    하지만, 운영체제마다 실행할 수 있는 기계어는 다르므로 하나의 자바 프로그램은 각자의 운영체제에 맞는 기계어로 번역되어야한다.

    이러한 이유로 JVM은 운영체젝 종속적으로 존재하게 되는 것이다.

     

     

    2. 컴파일 하는 방법

    컴파일(compile)은 우리가 컴퓨터와 대화하기 위해 사용하는 프로그래밍 언어(java, C, python 등)를 컴퓨터가 이해할 수 있는 0과 1로 이루어진 기계어로 번역하는 작업이다.

    Java가 기계어로 번역되는 컴파일 방법은 어떻게 될까?

    우리가 java로 개발을 하여 코드를 완성하면 확장자가 .java인 파일이 나오게 되고 이 파일을 소스 파일이라고 한다.

    이 소스 파일을 javac.exe라는 컴파일러(컴파일 역할을 하는 것)로 컴파일을 하면 확장자가 .class인 바이트 코드 파일이 생성된다.

    컴파일 과정

     

    3. 실행하는 방법

    소스 파일을 컴파일 작업을 마쳤다면 컴퓨터가 이해할 수 있는 기계어로 번역되었을 것이다.

    하지만, java는 다른 언어와 달리 컴파일 작업을 마치면 기계어가 아닌 바이트 코드로 이루어진 파일이 되기 때문에 컴파일 후 바로 실행이 되는 것이 아니다.

    바이트 코드 파일을 기계어로 번역하기 위해서는 JVM이 실행되어야하고 JVM을 구동시키는 명령어는 java.exe이다.

    java.exe 명령어가 실행되면 JVM은 바이트 코드 파일(*.class)를 메모리에 올리고 운영체제에 맞는 기계어로 번역한다.

    그리고 파일 내의 main() 메소드를 찾아 실행시키는 것이다.

    실행 과정

     

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

    위에서 언급한 바에 따르면 java 소스 파일은 컴파일 후 기계어로 된 자바 프로그램이 아닌 바이트 코드로 된 파일로 된다.

    그러면 바이트 코드는 무엇일까?

    사전적 의미를 보면 바이트 코드는 특정 하드웨어가 아닌 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법이다. 역사적으로 바이트코드는 대부분의 명령 집합이 0개 이상의 매개 변수를 갖는 1바이트 크기의 명령 코드(opcode)였기 때문에 바이트코드라 불리게 되었다.

     

    이 사전적 의미를 java 프로그램의 실행과정에 대입하여 이해해보면 명령 코드인데 JVM에서 실행되기 위한 명령 코드이다라고 이해할 수 있다. 그러니까 사람이 이해하기 쉬운 프로그래밍 언어도 아니고 컴퓨터가 이해하기 쉬운 기계어도 아니고 JVM과 같은 가상 기계(기계라고 말하지만 사실은 소프트웨어이다.)에서 이해할 수 있는 코드라는 것이다.

     

    그러면 굳이 왜 바이트 코드가 필요한 것일까?

    그 이유는 한번 프로그래머가 만든 프로그램을 각 운영체제에 맞게 만들 필요없이 하나의 프로그램을 개발하면 어떠한 운영체제에서도 실행 시킬 수있게 하기 위해서이다.

    만약, 바이트 코드가 없다고 생각해보자.

    java 프로그램은 컴파일을 거쳐 기계어로 될 것이다. 이 경우에 윈도우와 MAC이 이해하는 기계어는 서로 다르기때문에 소스 파일(프로그래머가 작성한 파일)을 운영체제별로 작성해야한다. JVM이 운영체제별로 있다고 하더라도 소스 파일 원본을 이해할 수 있는 능력은 없다.이렇게 되면 프로그래머 입장에서는 너무 귀찮은 일이 된다.바이트 코드가 있다면 프로그래머는 하나의 소스 파일만 만들어 컴파일 후 바이트 코드로 된 파일을 배포하면 JVM이 해당 운영체제에서 실행 하능한 기계어로 번역해주게 한다.

     

     

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

    JIT 컴파일러의 의미를 바로 알아보기 전에 JIT는 Just-In-Time의 약어로 한국어로 번역하면 적시에, 제 시간에라는 말이다. 그러면 단어의 의미로 직역해보면 제 시간에(혹은 적시에) 코드를 기계어로 번역해주는 프로그램이 JIT 컴파일러라고 이해할 수 있다.

    여기서 말하는 제 시간, 적시는 언제를 의미할까?

    컴파일이 필요한 이유는 프로그램을 실행시키기 위해서는 컴퓨터가 이해할 수 있는 기계어로 번역해주어야 하기 때문이다. 그러면 컴파일이 필요한 시점은 프로그램이 실행되는 시점이 제 시간, 적시라는 것을 알 수 있다.

     

    그러면 JIT 컴파일러는 자바 프로그램이 실행되는 과정에서 언제 도입되는 것일까?

    답을 먼저 말하면 JVM이 바이트 코드 파일을 기계어로 번역할 때 쓰인다.

    자바 소스 코드 파일을 바이트 코드 파일로 컴파일 한 후 다시 JVM을 통해 기계어로 번역한다면 다른 언어에 비해 속도가 느리다는 단점이 생기게 된다. 이러한 단점을 보완하기 위해 JVM 내부의 최적화된 JIT 컴파일러를 도입한 것이다.

     

    JIT 컴파일러는 바이트 코드를 읽어 빠른 속도로 기계어를 생성할 수 있고 이러한 기계어 변환은 코드가 실행되는 과정에 실시간으로 일어난다. 또한, 전체 코드를 한번에 기계어로 번역하는 것이 아니라 그 순간에 필요한 부분만 변환한다.

    기계어로 변환된 코드는 캐시에 저장되기 때문에 재사용시 컴파일을 다시 할 필요가 없다는 장점을 가지고 있다.

    출처: https://m.blog.naver.com/ki630808/221844888233

     

    6. JVM 구성 요소

    JVM의 구성요소는 Class Loader, Execution Engine, Garbage Collector, Runtime Data Area이다.

    하나씩 자세하게 알아보자.

    1) Class Loader

    자바 컴파일러에 의해 바이트코드로 변환된 파일을 읽어들여 Runtime Data Area부분에 적재하는 역할을 한다.

     

    2) Execution Engine

    Runtime Data Area에 적재된 바이트 코드 파일을 기계어로 변환하고 실행하는 역할을 한다.

    명령어는 인터프리터 방식으로 하나하나 실행되기도 하고, 위에서 언급한 JIT 컴파일러에 의해 적절한 시간에 바이트코드를 기계어로 변환하여 실행되기도 한다.

     

    3) Garbage Collector

    Heap 영역에 생성되어 있는 객체들 중 참조되지 않는 객체를 찾아 제거하는 역할을 한다.

     

    4) Runtime Data Area

    JVM의 메모리 영역으로 자바 프로그램을 실행할 때 사용되는 데이터들을 적재하는 영역이다.

     

    7. JDK와 JRE의 차이

    JDK는 Java Development Kit의 약어로 자바로 개발하는 것을 도와주는 키트이다.

    실생활 예를 들어 설명하면 응급치료키트를 보면 우리가 다쳤을 때 응급처지를 하기 위한 물품들이 들어있다.

    JDK도 자바 프로그램 개발에 필요한 JVM, 라이브러리 API, 컴파일러 등의 개발 도구가 포함되어 있다.

     

    JRE는 Java Runtime Environment의 약어로 자바 프로그램이 실행할 수 있는 환경을 제공한다.

    JRE에는 자바 프로그램 실행에 필요한 JVM, 라이브러리 API만 포함되어 있다.

     

    이렇게 둘의 정의와 어떠한 것을 가지고 있는지를 보면 자바 프로그램을 개발하고자 한다면 JDK를 설치해야하고

    단순히 자바 프로그램을 실행시키고만 싶다면 JRE만 설치하면 되는 것으로 보인다.

    또한, JRE가 가지고 있는 것들은 JDK가 모두 포함하고 있다.

    즉, JRE는 JDK에 포함 되어 있는 관계이다.

     

    JDK 내부에 JRE가 포함되어 있어 보통의 경우에 자바 프로그램을 개발하고 실행하고 싶다면 JDK만 설치하면 된다.

    하지만 웹 브라우저에서 실행하는 애플릿(Applet)은 JRE을 요구하기 때문에 애플릿을 개발하고자한다면 JRE도 함께 설치해주어야한다.

     

    JDK와 JRE 관계

     

    댓글

Designed by Tistory.