JVM이란?, #1 컴파일 언어와 인터프리터 언어의 차이

최동민·2022년 11월 14일
0

JDK와 JRE의 차이

JDK

Java Development Kit (자바 개발 키트)

Java 를 사용하기 위해 필요한 모든 기능을 갖춘 Java용 SDK (Software Development Kit)이다.
JDK 는 JRE를 포함하고 있다.
JRE에 있는 모든 것 뿐만 아니라 컴파일러(javac)와 jdb, javadoc 과 같은 도구도 있다.
즉, JDK는 프로그램을 생성, 실행, 컴파일할 수 있다.

JRE

Java Runtime Environment (자바 런타임 환경)

JVM + 자바 클래스 라이브러리(Java Class Library) 등으로 구성되어 있다.
컴파일 된 Java 프로그램을 실행하는데 필요한 패키지이다.
요약
JDK는 자바 프로그램을 실행, 컴파일, 개발용 도구.
JRE, JVM를 모두 포함하는 포괄적인 키트이다.
JRE는 자바 프로그램을 실행할 수 있게 하는 도구이다. JVM을 포함하고 있다.

JVM

Java Virtual Machine의 줄임말.

직역하면 '자바를 실행하기 위한 가상 기계(컴퓨터)'라고 할 수 있다.
Java 는 OS에 종속적이지 않다는 특징을 가지고 있다. OS에 종속받지 않고 실행되기 위해선 OS 위에서 Java 를 실행시킬 무언가가 필요하다. 그게 바로 JVM이다.
즉, OS에 종속받지 않고 CPU 가 Java를 인식, 실행할 수 있게 하는 가상 컴퓨터이다.

JVM의 역할에 대해 정리하자면, JVM은 JAVA와 OS사이에서 중개자 역할을 수행하여 JAVA가 OS에 구애받지 않고 재사용을 가능하게 해준다. 그리고 중요한 메모리관리, Garbage collection을 수행한다.

  • OS
    운영체제(運營 體制, 문화어: 조작 체계) 또는 오퍼레이팅 시스템(operating system, 약칭: OS)은 사용자의 하드웨어, 시스템 리소스를 제어하고 프로그램에 대한 일반적 서비스를 지원하는 시스템 소프트웨어이다.

JAVA 실행 과정


컴파일 과정을 알아보자.

Java 소스코드, 즉 원시코드(.java)는 CPU가 인식을 하지 못하므로 기계어로 컴파일을 해줘야한다.
하지만 Java는 이 JVM 이라는 가상머신을 거쳐서 OS에 도달하기 때문에 OS가 인식할 수 있는 기계어로 바로 컴파일 되는게 아니라 JVM이 인식할 수 있는 Java bytecode(
.class)로 변환된다.
그러니까 우선 JVM이 인식할 수 있는 바이트코드로 컴파일 된다는 것.

  1. Java compiler 가 .java 파일을 .class 라는 Java bytecode로 변환한다.
  • 💡 여기서 Java compiler는 JDK를 설치하면 bin 에 존재하는 javac.exe를 말한다. (즉, JDK에 Java compiler가 포함되어 있다는 소리임)
    javac 명령어를 통해 .java를 .class로 컴파일 할 수 있다.
  1. 변환된 bytecode는 기계어가 아니기 때문에 OS에서 바로 실행되지 않는다.
    이 때, JVM이 OS가 bytecode를 이해할 수 있도록 해석해준다. 따라서 Byte Code는 JVM 위에서 OS 상관없이 실행될 수 있는 것이다.
    OS에 종속적이지 않고, Java 파일 하나만 만들면 어느 디바이스든 JVM 위에서 실행할 수 있다.

바이트코드란 무엇인가

가상 컴퓨터(VM)에서 돌아가는 실행 프로그램을 위한 이진 표현법.

자바 바이트 코드(Java bytecode)는 JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미한다.
자바 컴파일러에 의해 변환된 코드의 명령어 크기가 1바이트라서 자바 바이트 코드라고 불리고 있다.

바이트 코드는 다시 실시간 번역기 또는 JIT 컴파일러에 의해 바이너리 코드로 변환된다.

  • 💡바이너리 코드란?
    바이너리 코드 또는 이진 코드라고 함
    컴퓨터가 인식할 수 있는 0과 1로 구성된 이진코드

  • 💡 기계어란?
    0과 1로 이루어진 바이너리 코드이다.
    기계어가 이진코드로 이루어졌을 뿐 모든 이진코드가 기계어인 것은 아니다.
    기계어는 특정한 언어가 아니라 CPU가 이해하는 명령어 집합이며, CPU 제조사마다 기계어가 다를 수 있다.

즉, CPU가 이해하는 언어는 바이너리 코드, 가상 머신이 이해하는 코드는 바이트 코드이다.

컴파일 언어 vs 인터프리터 언어

컴파일 언어

  • 소스 코드 전체를 컴파일 한 후 (기계어로 번역한 후) 기계어를 CPU/메모리를 통해 읽어 실행하는 방식으로 동작하는 언어

컴파일 언어 특징

  • 규모가 큰 프로그램은 컴파일 시 오래 걸릴 수 있다.
    컴파일 후에는 모든 소스코드가 기계어로 변환되어 있기 때문에 실행 시간이 빠르다.

컴파일 언어 종류

  • C, C++, Java, C#

  • 💡 빌드(Build) : 컴퓨터에서 이해할 수 있는, 즉 실행 가능한 파일로 만드는 과정이다.
    우리가 만든 소스코드를 '빌드'하면 실행 파일을 얻는다.
    실행파일은 exe, exec 등등 여러 종류가 있고,
    실행파일은 CPU가 읽을 수 있는 이진코드인 기계어(Machine Code)로 이루어져 있다.

인터프리터 언어 (스크립트 언어)

소스 코드를 컴파일하지 않고 인터프리터로 소스코드를 한 줄씩 번역하면서 실행하는 방식으로 동작하는 언어
인터프리터 : 프로그래밍 언어의 소스 코드를 바로 실행하는 컴퓨터 프로그램 또는 환경

인터프리트 언어의 장점

  • 빌드 과정 없이 바로 실행이 가능하다. → 별도의 실행 파일이 없다.
    컴파일과정 없이 바로 실행하기 때문에 수정, 디버깅에 유리하다. 즉 개발속도에 유리하다.
    각 플랫폼에 지원하는 인터프리터만 있다면 실행 가능하기 때문에 플랫폼에 독립적이다.

인터프리트 언어의 단점

  • 컴파일을 하지 않고 인터프리터가 직접 한 줄씩 읽어서 실시간으로 실행하기 때문에 컴파일 언어에 비해 속도가 느리다. → 번역과 실행이 동시에 이루어진다.
    하드웨어 스펙이 높아짐에 따라 실행 차이를 체감하기 어려운 추세다.
    개발자가 읽기 어려운 컴파일 언어 프로그램과는 달리, 코드를 열면 알아볼 수 있기 때문에 보안 상 작업이 필요하다. (난독화)

인터프리터 언어 종류

  • R, Python, Ruby

인터프리터 언어와 컴파일 언어 실행 구조 비교

컴파일러는 소스코드 전체를 CPU가 읽을 수 있는 기계어로 변환한다.
인터프리터는 소스코드 각 행을 기계어로 번역한다.

그래서 오류가 나면 컴파일러는 컴파일 하는 도중에 오류가 나고,
인터프리터는 분석 도중 어느 행에 오류가 발생하면 그것을 알려주고 그 이후의 분석을 멈춘다.


JIT 컴파일러

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

JIT 컴파일(just-in-time compliation) 또는 동적 번역(dynamic translation) 이라고 한다.
JIT 컴파일러는 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러이다.

  • 인터프리터 방식의 단점을 보완하기 위해 도입되었다.
    인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 해당 더 이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식이다.
  • 기계어(컴파일된 코드)는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행하게 된다.
    물론 JIT 컴파일러가 컴파일하는 과정은 바이트 코드를 인터프리팅하는 것보다 훨씬 오래걸리므로 한 번만 실행되는 코드라면 컴파일 하지 않고 인터프리팅하는 것이 유리하다.
    따라서 JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넣을때에만 컴파일을 수행한다.

자바에선 자바 컴파일러가 자바 프로그램 코드를 바이트 코드로 변환한 다음,
실제 바이트 코드를 실행하는 시점에서 자바 가상 머신(JVM, 정확히는 JRE)이 바이트 코드를 JIT 컴파일을 통해 기계어로 변환한다.

profile
코드를 두드리면 문이 열린다

0개의 댓글