Java

[Java] JVM과 Java 컴파일

DH_0518 2024. 1. 19. 02:29

자바의 큰 특징 중 하나는 Mac이든 Linux든 Windows든 어떤 OS에도 영향을 받지 않고 독립적으로 실행될 수 있다는 것이다.

이는 자바가 JVM(Java Vitual Machine) 위에서 동작하기 때문에 가능한 것이다. 그렇다면 JVM이 어떻게 동작하기에 자바가 OS에 영향을 받지 않고 독립적으로 실행될 수 있는지, 그리고 컴파일 과정은 어떻게 되는지 알아보도록 하자.

 

 

 

Compiled vs Interpreter

 

그렇다면 컴파일 과정을 알기 전에, 컴파일이 무엇인지 알아보자

컴퓨터 언어는 크게 컴파일(Complie) 언어와 인터프리터(Interpreter) 언어로 나뉜다. 컴파일 언어는 프로그램 실행 전, 소스 코드 전체를 기계어로 변환하는 컴파일을 수행하는 단계가 필요한 언어이고, 인터프리터 언어는 컴파일 언어와 반대로 소스 코드를  한 줄씩 해석하고 실행하는 언어를 말한다.

 

컴파일 언어(Complied Language)

  • 프로그램 실행 전 고급 언어로 작성된 소스 코드 "전체"를, 컴퓨터(OS)가 한번에 처리할 수 있는 기계어나 어셈블리어로 번역하는 과정이 필요하다. 이를 컴파일이라 한다
  • 컴파일 단계에서 시간이 조금 걸리지만, 한번 컴파일 된 코드는 이후에 빠르게 실행할 수 있다
  • 컴파일된 코드는 실행되는 해당 플랫폼이 읽을 수 있는 언어로 번역하는 과정이므로, 특정 플랫폼에서 의존적이기에 한번 컴파일된 코드를 다른 플랫폼에서 실행하려면 재컴파일 과정이 필요하다

인터프리터 언어(Interpreter Language)

  • 컴파일 언어와 다르게 전체를 번역하지 않고, 프로그램이 실행되면 코드를 한 줄씩 읽어 내려가며 곧바로 실행된다
  • 컴파일 시간은 없지만, 한 줄씩 인터프리트 하는 과정이 컴파일된 코드를 실행하는 것 보다 훨씬 느리므로, 전체적으로 보면 실행 시간이 컴파일 언어보다 느리다

 

 

Java Complie Process

 

그렇다면 컴파일 언어는 특정 플랫폼에 의존적인데, 자바는 어떤 컴파일 과정을 거치기에 OS에 영향을 받지 않고 독립적으로 실행이 되는 걸까? JVM에서 그 이유를 찾을 수 있다. JVM은 각 OS에 맞게 컴파일을 시켜줘야 하는 기존의 불편하고 효율적이지 못한 방식을 개선하여, 각 OS에 맞게 자동 번역을 해주는 역할을 하는 것이라 생각하면 된다. 이러한 자동번역기가 존재한다면 어떠한 OS에서 동작을 하더라도 컴파일 과정을 걱정할 필요가 없는 것이다.

 

 

자바 컴파일 과정에 필요한 사전 지식

  • 자바의 컴파일
    • OS가 아닌, JVM을 대상으로 하는 컴파일이다
    • 컴파일은 JDK(Java Development Kit)나 JRE(Java Runtime Environment)에 함께 포함되는 javac.exe 실행 파일이 수행한다
    • 자바 클래스 파일인 ".java" 파일을 컴파일하여 파일에 존재하는 모든 클래스를 각각 생성하고, 이 코드는 ".class" 파일로 바이트코드(Bytecode)라고 한다
  • 바이트코드
    • 컴파일 결과이지만 C나 C++에서 컴파일 하여 생성된 "기계어"와는 달라서 컴퓨터는 읽을 수 없고, JVM이 읽을 수 있다
    • "기계어"는 JVM이 다른 모듈을 통해서 생성하고 실행하는데, C나 C++과 비교하면 조금 느린 성능을 낸다
  • JVM의 클래스 로더(Class Loader)
    • JVM의 요소중 하나로, 바이트코드를 읽어들여 JVM의 메모리에 올라갈 실제 class 객체를 생성하는 역할을 한다
    • 즉, JVM에서 class를 요청하면 해당 class의 바이트코드를 읽어 메모리로 로딩하는 역할을 한다고 생각하면 된다
    • 동적 로딩(컴파일 타임에 존재하는 모든 class를 한번에 로딩하는 것이 아니라, 로드타임이나 런타임에서 실행에 필요한 class를 그때그때 로딩하는 방식)을 통해 가져오므로, 메모리 관점에서는 효율적이지만 시간 측면에서는 성능이 조금 떨어진다
  • Java 실행 엔진(Execution Engine)
    • 자바 실행 엔진은 Interpreter 방식과 JIT 컴파일러 방식, 두 개를 혼합하여 동작한다
      • 인터프리터(Interpreter) 방식
        : 바이트코드를 한 줄씩 읽고 실행한다. 하나하나의 실행은 빠르지만, 반복적으로 실행되는 코드가 있다면 반복해서 해석해야하기 때문에 전체적인 성능은 떨어진다
      • JIT 컴파일러 (Just-In-Time Complier)
        : 컴파일 타임이 아닌, 프로그램을 실행하는 런타임시에 바이트코드를 컴파일 하는 컴파일러이다.

 

 

자바 실행 엔진의 동작

  1. java 파일을 실행하면, ".java" 파일을 JVM이 읽을 수 있는 ".class" (바이트코드)파일로 컴파일한다
  2. JVM의 클래스 로더가 바이트코드를 읽어들여 JVM의 메모리에 로딩한다
  3. Java 실행 엔진의 interpreter에 의해 한 줄씩 바이트코드가 해석되고 실행된다
  4. JIT 컴파일러는 실행중에 어떤 부분이 반복적으로 실행되는지 모니터링하고, 반복적인 부분이 발견되면 그 부분을 컴파일한다
  5. JIT 컴파일러는 컴파일된 코드를 최적화한 후, 인터프리터 대신에 컴파일된 바이트코드를 실행한다

이러한 Interpreter + JIT Complier를 통해서 Java는 인터프리터나 컴파일러만을 사용했을 때보다 더욱 효율적으로 동작할 수 있고, 특정 운영체제나 아키텍처에 의존하지 않는 중간 코드인 바이트코드를 통해 독립적으로 실행될 수 있는 것이다.

 

 

 

 

 

 

 

 

 

 

 

Reference

 

[Java] 컴파일 과정 | 👨🏻‍💻 Tech Interview

[Java] 컴파일 과정 들어가기전 자바는 OS에 독립적인 특징을 가지고 있다. 그게 가능한 이유는 JVM(Java Vitual Machine) 덕분이다. 그렇다면 JVM(Java Vitual Machine)의 어떠한 기능 때문에, OS에 독립적으로

gyoogle.dev

 

[Java] 컴파일(Compile) 개념과 자바 컴파일 이해하기

자바(Java)의 경우 컴파일(Compile)이라는 개념이 들어갑니다. 파이썬(Python)과 같은 언어는 컴파일 언어와 다르게 인터프리터 언어로 별도의 컴파일 과정이 없이 소스 코드를 한줄 한줄 읽어가면서

needneo.tistory.com

 

[조금 더 깊은 Java] Java Bytecode 를 알아보자 (자바를 컴파일하면 어떤 일이 일어날까?)

우리는 많은 시간 Java를 이용해서 다양한 소프트웨어를 개발하면서 들었던 소리가 있다. Java는 JVM 이 있기 때문에 플랫폼에 종속적이지 않고 이식성이 뛰어나다. 그 이유에 대해서 생각해본 경

wonit.tistory.com

 

[JAVA] 로드타임, 런타임 동적로딩 (Load-Time, Run-Time Dynamic Loading)

JVM은 ClassLoader를 이용해 필요한 Class를 Loading 한다 ClassLoader는 Class가 참조되는 순간 동적으로 Load 및 Link가 이루어지는 Dynamic Loading을 담당하는 주체이다 즉 JVM내로 Class를 Load, Link를 통해 적절히

kkang-joo.tistory.com

 

인터프리터, 컴파일, JIT 컴파일

들어가기 전에 우리가 작성한 코드가 컴퓨터에서 실행되기 위해서는 0과 1로 이루어진 컴퓨터가 인식할 수 있는 기계어로 변역되어야 한다. (C, 자바, C++, 자바스크립트 등과 같은 프로그래밍 언

miracleground.tistory.com