#jvm

JVM에 관하여 - Part 1, JVM, JRE, JDK

JVM에 관하여 - Part 1, JVM, JRE, JDK

자바로 작성된 코드는 어떻게 돌아가는 걸까? 해당 물음에 답을 찾기 위한 JVM 시리즈 1편, JVM, JRE, JDK에 관한 글입니다. 이번 글에서는 배포 환경 혹은 개발 환경을 세팅하면서 설치를 하였던 JRE와 JDK가 무엇인지에 대해서 다루게 되었습니다.


Java 프로그램 배포 및 개발 환경 세팅

개발을 공부하면서 주어진 환경에서 진행하는 것이 아닌 스스로 개발, 배포 그리고 운영 환경을 구축하게 되었습니다. 저희 팀도 AWS의 EC2를 사용하여 LinuxUbuntu 배포판 위에서 Java 프로그램의 개발 및 배포 환경을 설정하였습니다. 이때 습관처럼 다음과 같은 명령어를 입력하게 되었습니다.

sudo apt -y install default-jre default-jdk

항상 잘 사용하던 명령이지만 다른 프로그래밍 언어인 Python 이나 Run Time 환경인 Nodejs 와 비교했을 때 낯섦이 느껴졌습니다. 난 Java 를 직접적으로 설치하지 않고, default jdkdefault jre 라는 관계없어 보이는 것을 설치하는 걸까? 이번 포스팅에서는 위의 질문에 대한 답을 찾아갑니다.

JVM 이란

설치한 수수께끼의 두 프로그램을 알기 위해서는 이번 시리즈의 주인공인 JVM 에 대해서 이해를 해야 합니다. JVMJava Virtual Machine 의 약자로 Java 로 작성된 프로그램이 돌아가도록 만들어주는 프로그램입니다. Java 로 작성된 프로그램은 운영체제에 맞는 실행 파일로 컴파일되는 것이 아닌 .class 라는 확장자를 가진 파일로 변환이 됩니다. 변환된 .class 파일은 JVM 위에서 작동이 됩니다. 이때, 미리 설치된 JVM 은 운영체제 별로 동일하게 작동하도록 .class 파일에게 환경을 제공합니다.

images

이 과정을 통하여 Java 는 큰 장점을 얻을 수가 있었습니다. 그것은 바로 높은 이식성입니다. 어느 기기나 운영체제에 상관없이 JVM 이 설치 및 구동될 수 있는 환경이라면 Java 로 작성한 프로그램은 실행이 가능합니다. 그 때문에 다른 운영체제에 맞춰서 컴파일을 해줘야 하는 다른 언어보다 높은 이식성을 가질 수 있게 되었습니다.

JRE 이란

JVM 은 우리가 작성한 코드를 기반으로 한 .class 확장자를 가진 클래스 파일이 작동할 수 있도록 환경을 제공해줍니다. 하지만 원활하게 작동하기 위해서는 코드에 작성된 내용만으로 가능하지는 않습니다. JVM 위에서 프로그램이 원활하게 실행을 하기 위해서는 몇 가지 필수적인 요소들이 필요합니다.
이를 제공해주는 것이 JRE, Java Runtime Environment 입니다. JRE 는 크게 JVM , Java Class Libraries 그리고 Class Loader 라는 요소로 구성이 됩니다. Java Class LibrariesJava 를 실행시키는데 필수적인 라이브러리입니다. java.io , java.util , java.thread 등 작동에 필수적인 요소들을 가지고 있습니다.

예시 코드와 바이트 코드를 살펴보도록 하겠습니다.

//Java 코드
public class Main {
  public static void main(String[] args) {
    int a = 1;
    System.out.println(a);
  }
}

//바이트코드
... 중략 ...
  L0
    LINENUMBER 3 L0
    ICONST_1
    ISTORE 1
   L1
    LINENUMBER 4 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (I)V
   L2
    LINENUMBER 5 L2
    RETURN
   L3
    LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
    LOCALVARIABLE a I L1 L3 1
    MAXSTACK = 2
    MAXLOCALS = 2
...

위에서 보는 것처럼 JVM 에 올라가는 클래스 파일의 바이트 코드에서도 필수 라이브러리를 참고하고 있습니다. 이 때문에 간단한 코드라도 필수 라이브러리가 필요하다는 것을 알 수가 있습니다. Class Loader 는 필요한 클래스들을 JVM 위로 올려주는 역할을 합니다. 자세한 연결 및 작동 과정은 다음 포스팅에서 다루도록 하겠습니다. JRE 의 구성요소들을 통해서, JVM 은 원활히 작동할 수가 있습니다.
하지만 JRE 는 개발에 사용되는 것이 아닌 실제 프로그램을 구동시키는 데 집중을 하고 있습니다. 실제 Java 코드가 주어져도 이를 분석하거나 클래스 파일로 변환하는 일은 할 수 없습니다. Java Compiler 를 비롯한 개발에 필요한 요소들은 없기 때문에 개발을 하기 위해서는 다른 요소들이 더 필요합니다.

JDK이란

JDK, Java Development Kit 의 약자로 Java 를 활용하여 프로그램을 개발할 때 필요한 도구 모음입니다. 이때, 실제로 프로그램을 실행시켜보아야 하기 때문에 JRE 가 포함이 되어 있습니다. 이를 확인하기 위해 JREJDK , 그리고 관련된 의존성을 삭제한 후에 다시 JDK 만 설치를 해보았습니다.

images

위에서 보이는 것처럼 JDK 만 설치를 하였을 뿐인데, JRE 도 자동으로 설치되는 것을 알 수가 있습니다. 그렇다면 JDKJRE 이외의 어떤 구성 요소들이 추가된 것일까요? 대표적으로는 Java 로 이루어진 코드를 클래스 파일로 컴파일하는 javac 의 기능, 작성된 코드를 디버깅 하는 jdb 기능 등을 가집니다.
JDK 에서도 개발과 실행에 필요한 환경 및 기능 제공의 폭에 따라 표준형인 SE(Standard Edition) 과 여러 기능이 추가된 EE(Enterprise Edition) 으로 나뉩니다. 하지만 이런 버전 구분 이외에도 출시된 순서에 따라서 숫자로 버전을 구분하는 방법도 있습니다.

가장 널리 쓰이는 버전 JDK 버전 8

최근까지도 다양한 버전이 출시되고 있는 Java 이지만 유독 8 버전이 널리 쓰이는 것을 볼 수가 있습니다. 8 버전 이외에도 UbuntuDebian 배포판의 Repository 에서는 11 버전이 기본으로 제공되고 있습니다. 개발뿐만이 아니라 코딩테스트에서도 이 두 버전만 널리 쓰이게 됩니다. 왜 8 버전과 11 버전이 자주 쓰이게 되는 것일까요?
Java 는 유명한 Linux 배포판이나 개발 관련 Runtime Environment, Library 와 마찬가지로 여러 버전으로 배포됩니다. 그중 하나가 바로 LTS, Long Term Support 개념입니다. LTS 의 경우에는 다른 버전보다 안정적이며, 제작한 기업이나 오픈 소스 관리 측에서 긴 기간을 관리해주겠다라는 것을 명시합니다. 일반적으로 각 배포판들은 약 6개월 정도의 지원 기간을 가집니다. 하지만 LTS 의 경우에는 짧게는 5년 길게는 그 이상을 지원합니다. 때문에 많은 개발자들은 새로운 기능 빨리 적용하기 보단 상대적으로 안심하고 오랜 기간 사용할 수 있는 LTS 버전을 선호하게 되었습니다.
가장 많이 쓰이는 8 버전은 Java 의 최초 LTS 버전이며, Java 개발사 Sun MicrosystemsOracle 에 인수되고 나서 출시되었습니다. 그 다음으로 많이 쓰이는 11 버전도 LTS 버전이며, 8 버전 출시 4년 후에 나오게 되었습니다. 현재 나온 최신 버전인 16 버전은 LTS 버전이 아니며, 다음 17 버전이 LTS 로 예정이 되어 있습니다.

open JDK와 Oracle JDK, 다양한 JDK 버전들

EC2에 기본적인 개발환경을 모두 세팅하고 난 다음에, CI & CD 를 위하여 Jenkins 를 사용하게 되었습니다. 이 때, Jenkins 는 배포하는 서버와 다른 CI & CD 전용 서버에서 운영되기 때문에 또 다시 JDK 를 설치를 해주어야했습니다. 하지만 Jenkins 에서는 항상 보던 open JDKdefault JDK 가 아닌 Oracle JDK 를 권장하고 있었습니다.

images

Java 를 소유하고 있는 회사는 Oracle 인건 인지하였지만, 기존의 사용하던 open JDK 와는 다른 것을 알게 되었습니다. Oracle JDKOracle 에서 관리하는 JDK 입니다. 상업적으로 사용하려면 비용을 지불해야하지만, 상대적으로 지원 정도가 높습니다. 또한, open JDK 에서 지원하지 않는 라이브러리를 가지고 있습니다. open JDK 는 오픈소스로 운영이 되며, 상업적으로 사용해도 무료입니다. 많은 Linux 배포판에서 저장소에 기본으로 등록이 되어 있습니다. open JDK 는 상대적으로 지원 정도가 약하지만, 웹 개발에서는 큰 차이가 나지 않는다고 합니다. 이 때문에 많은 사용자들이 open JDK 를 현재 사용하고 있습니다.

마치며

이번 포스팅에서는 JAVA 를 구동시키는데 필수적인 JVM , JRE , JDK 를 알아보았습니다. 그 중 JVMJAVA 에서 GC , 메모리 관리 등이 이뤄지는 핵심적인 요소입니다. JVM 의 구성 요소 및 작동 방식은 다음 포스팅에서 다루도록 하겠습니다.

References