자바 - JVM(자바의 동작 과정)

2024. 3. 11. 10:12백엔드/자바

JVM이란 무엇인가?

아래에 나올 모든 내용들은 위의 질문에서 초래되었다. 처음에 자바를 공부할 때만 해도 JVM이란 단어는 생소하기도 했고, 굳이 알 필요가 없다고 생각해 대충 넘겼던 기억이 난다. 그런데 이번에 다시 자바를 공부하던 중 '대체 자바란게 어떻게 돌아가는 거지?'라는 의문이 강하게 생겼다. 그랬더니 과거에 배운 JVM(Java Virtual Machine)이란 단어가 떠올랐고, 떠오른 김에 한 번 파보자!라는 마음이 들어 공부를 하게 되었다. 이 글은 체계적으로 JVM을 설명한다기보단 JVM을 알기 위해 공부를 하다 보면 자연스레 떠오르는 물음에 대답을 하는 방식으로 구성된다. 물론 그 질문은 IT에 관심이 많은 "까비"라는 도깨비 친구가 대신해 줄 것이다.

 

JVM

 

JVM은 'Java Virtual Machine'을 줄인 것으로 직역하면 '자바를 실행하기 위한 가상 기계'라고 할 수 있다. 자바로 작성된 어플리케이션은 모두 이 JVM에서만 실행되기 때문에, 자바 애플리케이션이 실행되기 위해선 반드시 JVM이 필요하다.

 

왼쪽은 일반적인 컴파일러 언어이다. 이를테면 C, C++ 같은 것들 말이다. 일반적인 프로그램은 OS만을 거쳐 하드웨어로 전달된다. 반면 자바는 JVM을 한 번 더 거치기 때문에, 그리고 하드웨어에 맞게 완전히 컴파일된 상태가 아니고 실행 시에 해석(interpret)되기 때문에, 속도가 느리다는 단점을 가지고 있다. 그러나 요즘엔 JLT 컴파일러와 향상된 최적화 기술이 적용되어 속도의 격차가 많이 줄었다.

 

???: 잠깐만요. 

 

JVM: 왜 그러니? 그리고 넌 누구니?

 

???: 안녕하세요 전 까비인데요. 대체 컴파일러 언어는 뭐고 해석(interpret)은 무슨 뜻이에요?

 

JVM: 우스꽝스러운 이름을 가지고 있구나. 그래 컴파일러와 인터프리터를 알고 싶다는 거지?

 

까비: 네

 

JVM: 그렇구나 간단히 요약하면 컴파일은 전체를 한 번에 번역하고, 인터프리터는 한 번에 한 문장씩 번역을 한단다.

 

까비: 잘 모르겠는데요?

 

JVM: 그럴 줄 알고 준비해놨지.

 

컴파일러(complier)와 인터프리터(interpreter)의 차이

우리가 코드를 짜는 이유는 코드를 실행했을 때 컴퓨터가 코드에 쓰인 대로 행동하도록 하기 위함이다. 하지만 컴퓨터의 뇌와도 같은 CPU는 사람이 사용하는 언어(고급 언어)를 이해할 수 없다. CPU는 수많은 반도체로 이루어져 있고, 하나의 반도체는 전기가 흐르는지(1), 흐르지 않는지(0)에 따라 1과 0만을 인식하고 나타낼 수 있기 때문이다. 따라서 사람이 쓰는 개발 언어(C, C++, Java, Python 등)를 기계어(1001011...)로 번역해 주는 것이 컴파일러(Compiler)와 인터프리터(Interpreter)이다. 두 가지는 모두 목적이 같지만 기계어로 번역되기까지 작동하는 방식과 개발 언어의 특성에 따라 차이점이 있다.

 

Compiler

Compile은 엮다는 뜻이다. 우리가 보통 '책을 엮는다'라는 표현은 출판사가 하나의 책을 처음부터 끝까지 만들어낼 때 쓴다. 마찬가지로 컴퓨터에서 컴파일러(Compiler)는 출판사처럼 프로그램 전체를 스캔하여 이를 모두 기계어로 한 번에 번역한다. 여기서 장점과 단점이 나온다.

 

Compiler의 장점

  • 1. 초기 스캔은 오래 걸리지만, 한번 스캔을 마치면 실행 파일을 만들어 놓고 계속 사용하기 때문에 실행 속도는 인터프리터보다 빠르다.
  • 2. 컴파일러는 오류 메시지를 생성할 때 전체 코드를 검사한 후에 오류 메시지를 생성한다. 따라서 프로그램 실행 전에 오류를 발견할 수 있다.

Compiler의 단점

  • 1. 프로그램을 실행하는데 필요한 모든 파일을 스캔하기 때문에 초기 스캔 시간이 오래 걸린다. 
  • 2. 컴파일러는 기계어로 번역시 오브젝트 코드(Object Code)라는 파일을 만든다. 이 코드를 다시 묶어서 하나의 실행 파일로 다시 만드는 링킹(Linking) 작업을 해야 한다. 따라서 보통 인터프리터보다 메모리를 더 많이 사용한다.

까비: 오브젝트 코드랑 링킹 작업은 또 뭐예요?

 

JVM: 여기선 크게 중요하지 않은 개념이니 가볍게 넘어가자꾸나. 우리가 책을 엮을 때도 종이 한 장 한 장을 엮어서  하나의 책을 만들어 내지?

 

까비: 그렇죠.

 

JVM: 왜 여러 종이를 써서 한 권의 책을 만들까? 그냥 종이 한 장에다 모든 글씨를 다 써도 되지 않겠니?

 

까비: 에이 그럼 종이가 너무 커질 거 아니에요. 그걸 누가 들고 다녀요!

 

JVM: 마찬가지란다. 방대한 하나의 코드는 다루기가 힘드니 여러 개로 나누어 번역을 한 후 마지막에 링킹(Linking)이라는 작업을 통해 하나로 묶는 거지!

 

까비: 그렇군요.

 

컴파일러(Compiler)를 사용하는 대표적인 언어에는 C, C++, CLEO, COBOL 등이 있다. 이렇게 컴파일러를 사용하여 실행하는 언어를 컴파일러형 언어(Compiled Language)라고 한다. 

 

Interpreter

Interpret는 "해석하다"라는 뜻이다. 한국에서 살다 보면 한 번쯤은 영어 문장을 해석했던 경험이 있을 것이다. 우리가 문장을 해석할 땐 한 줄 한 줄 해석한다. 만약 우리가 컴파일러였다면 원문으로 된 해리포터를 끝까지 다 읽고 나서야 해리포터가 사실은 마법사였다는 것을 알 수 있을 것이다. 하지만 다행히도 우린 타고난 인터프리터이기 때문에 해리포터의 흥미진진함을 느낄 수 있다. 인터프리터도 마찬가지다. 인터프리터는 프로그램 실행 시 한 번에 한 문장씩만 기계어로 번역한다.

 

Interpreter의 장점

  • 1. 컴파일러처럼 오브젝트 코드를 만들지 않고, 링킹 과정도 거치지 않기 때문에 메모리 효율이 좋다.
  • 2. 코드 변경 시 빌드 과정 없이 바로 실행이 가능하다. 따라서 개발 속도가 빠를 수 있다.

Interpreter의 단점

  • 1. 컴파일러와 다르게 한 번에 한 문장씩 번역하여 실행시키는 과정을 반복하여 실행 시간이 느리다.
  • 2. 한 번에 한 문장씩 읽기 때문에 프로그램을 실행해야만 오류를 발견할 수 있다.

인터프리터를 사용하는 대표적인 언어에는 Python, R, Ruby 가 있다. 이렇게 인터프리터로 실행되는 언어를 해석형 언어(Interpreted Language)라고 한다. 그리고 실제론 인터프리터 언어와 스크립트 언어(Script Language)를 혼용해서 쓰곤 한다.

 

 

 

JVM: 이제 컴파일러와 인터프리터가 이해 됐니?

 

까비: 네 확실하게 이해했어요!

 

JVM: 정말이니? 조금 의심스럽지만 알겠구나...

 

까비: 그런데 아저씨는 인터프리터 언어예요? 컴파일 언어예요?

 

JVM: 허허 나날이니? 그건 이 글을 다 읽으면 알 수 있을 거란다!

 

까비: ...

 

JVM: 그렇다면 혹시 정적 언어와 동적 언어에 대해선 들어봤니?

 

까비: 정적 언어? 동적 언어? 처음 들어봐요!

 

JVM: 그래 내 이것도 가르쳐주고 넘어가는 게 좋겠구나

 

정적 언어 vs 동적 언어

정적 변수(Static Variables)란 프로그램이 실행되는 동안 메모리에 고정된 주소를 가지고 있는 변수를 의미한다. 이 변수들은 프로그램이 실행될 때 메모리에 할당되며, 프로그램이 종료될 때까지 유지된다. 함수 내에서 선언되었을 경우 해당 함수가 호출될 때마다 초기화되지 않는다.

 

반면 동적변수(Dynamic Variables)는 프로그램 실행 중 동적으로 메모리에 할당되고 해제되는 변수를 의미한다. 프로그램이 실행 중일 때 유연하게 사용될 수 있는 변수이다.

 

정적타입 언어(Statically typed language)

정적타입 언어는 작성자가 소스 코드를 보고 변수 타입을 직접 작성하는 언어이다. 정적타입 언어에는 C, C#, C++, Java 등의 언어가 있고, 동적타입 언어에선 변수에 들어갈 값의 형태에 따라 자료형을 지정해주어야 한다. 컴파일 시 자료형에 맞지 않은 값이 들어있으면 컴파일 에러가 발생한다.

 

장점

  • 타입 에러로 인한 문제점을 초기에 발견할 수 있어 타입 관련한 런타임 오류를 방지할 수 있고 타입의 안정성이 높다.
  •  컴파일 시에 미리 타입을 결정하기 때문에 실행 속도가 빠르다.
  •  코드의 가독성이 좋아 다수의 협업이나 프로젝트를 할 때 유지보수에 유리하다.

단점

  • 코드를 작성할 때마다 변수의 타입을 결정해주어야 한다.

 

동적타입 언어(Dynamically typed languaged)

동적타입 언어는 코드를 실행할 때 알아서 변수 타입을 판단해 주는 언어이다. 동적타입 언어에는 JavaScript, Ruby, Python 등의 언어가 있다. 동적타입 언어는 컴파일 시 자료형을 정하는 것이 아닌 실행 시 인터프리터에 의해 데이터 타입이 자동으로 결정된다. 이는 변수가 언제든지 다른 데이터 타입의 값을 가질 수 있음을 의미한다.

 

장점

  • 코드 실행 시 자동적으로 변수의 타입을 판단하여 지정해 준다.
  • 타입을 매번 지정하지 않아도 되기 때문에 개발자가 빠르게 코드를 작성할 수 있다.

단점

  • 실행 도중에 변수에 예상치 못한 자료형이 들어와 타입 에러가 발생할 수 있다.
  • 타입 관련 에러는 런타임 시 확인 가능하기 때문에 코드가 길고 복잡해질 경우엔 타입 에러를 찾기 어려워진다.

 

 

까비: 그럼 할아버지는 정적타입 언어군요?

 

JVM: 그렇단다!

 

까비: 그럼 할아버지는 컴파일 언어일 것 같은데요?

 

JVM: 과연 그럴까?

 

까비: ...?

 

JVM: 그건 이 글을 다 읽으면 알 수 있을게다! 자 나에 대해 소개를 계속 이어 나가야지!

 

JVM(이어서)

JVM의 쓰임새를 한 문장으로 설명하면 "Wirte once, Run everywhere"이다. 한 번 쓰기만 하면 어디서든 작동한다. 다시 말해 OS마다 따로 코드를 작성해야 하는 번거로움 없이 자바가 플랫폼에(윈도우든 맥OS든) 독립적일 수 있게 만들어준다.

 

예를 들어 C언어의 경우 기계어를 바로 컴파일하므로 하드웨어 기종에 맞게 컴파일되어야 한다. 이를 '플랫폼에 종속적이다'라고 한다. 반면 자바는 중간 단계 언어로 컴파일하여 어떤 OS든 JVM만 설치되어 있다면 하드웨어 기종에 상관없이 단 한 번만 컴파일하면 된다. 이를 '플랫폼에 독립적이다'라고 한다.

 

 

까비: 여기 제가 어제 짠 java 코드가 있는데요. 이것도 번역할 수 있어요?

 

JVM: 어디 보자 System.out.println("안녕 나는 까비야!"); 라고 적어놨구나. 음... 미안하지만 나는 읽을 수 없겠는걸?

 

까비: 네? 왜요? 아저씬 뭐든 읽을 수 있는 거 아니었어요?

 

JVM: 허허 아니란다. 나는 .java 파일은 읽을 수 없고 .class 파일이라는 바이트 코드만 읽을 수 있단다!

 

까비: 바이트 코드요?

 

JVM의 실행 과정

자바 파일의 실행 과정을 크게  세 부분으로 나누면 

  1. 더보기
    .java 파일(소스 파일)을 .class 파일(바이트 코드)로 변환 (예비 번역)
  2. 더보기
    Class Loader가 JVM의 메모리(Runtime Data Areas)에 로드. (작업대에 올림)
  3. 더보기
    Excution Engine이 로딩된 클래스의 바이트 코드를 해석한다. (본 번역)

으로 나눌 수 있다.

JVM의 구성 요소

 

바이트 코드

 

 

바이트 코드란 가상 컴퓨터에서 작동하도록 만든 이진코드이다. 자바 바이트코드란 JVM이 이해할 수 있는 언어로 변환한 코드로 명령어의 크기가 1byte라서 자바 바이트 코드라고 불린다. 자바 코드를 배포하는 가장 작은 단위이고 확장자는 .class이다. 

 

Class Loader

클래스를 JVM의 메모리에 로드한다. 로딩된 클래스들을 Runtime Data Area에 배치한다. 코드를 실행하면 동적으로 클래스를 로드하고 jar파일 내 저장된 클래스들을 JVM 위에 탑재한다.

 

Excution Engine

클래스를 실행시키는 역할이다. Class Loader가 JVM내에 Runtime Data Areas 영역에 코드를 배치시키면 이것은 Excution에 의해 실행된다. 자바 바이트 코드(*.class)는 기계가 바로 수행할 수 있는 언어보다는 인간이 보기 편한 형태로 기술된 것이다. 그래서 Excution Engine은 이와 같은 바이트 코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경한다. 

 

Interpreter

Excition Engine은 자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 하지만 한 줄씩 수행하기 때문에 느리다는 단점이 있다.

 

JIT(Just-In-Time) Compiler

인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 더 이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식이다.

 

Garbage Collector

더 이상 사용되지 않는 인스턴스를 찾아 메모리에서 삭제한다.

 

Runtime Data Area

JVM이 프로세스로 수행되기 위해 OS로부터 할당받는 메모리 영역이다. 저장 목적에 따라 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack 5가지 영역으로 나뉜다.

 

 

Method Area(= Class Area = Static Area)

모든 Thread에게 공유된다. 클래스 정보를 처음 메모리 공간에 올릴 때 초기화 되는 대상을 저장하기 위한 메모리 공간. 클래스 정보, 변수 정보, Method 정보, static 변수 정보, 상수 정보 등이 저장된다.

 

까비: 잠깐만요! Thread가 뭐예요? 

 

JVM: 허허 스레드(Thread)가 궁금했구나. 이 스레드에 대해서도 나중에 한 번 공부해 봤으면 좋겠구나. 스레드란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미한단다. 모든 프로세스에는 한 개 이상의 스레드가 존재해 작업을 수행하지.

 

까비: 프로세스는 뭔데요?

 

JVM: 음 프로세스란 단순히 실행 중인 프로그램을 말한단다. 다시 말해서 사용자가 작성한 프로그램일 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 말하지. 스레드는 바로 이 프로세스 안에 들어있는 거란다. 또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 말할 수 있겠구나.

 

까비: 그렇군요

 

  • Runtime Constant Pool

스태틱 영역에 존재하는 별도의 관리영역. 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.

 

Heap Area

모든 스레드에게 공유된다. 객체를 저장하는 가상메모리 공간이다. new 연산자로 생성되는 객체와 배열을 저장한다. Class Area(Static Area)에 올라온 클래스들만 객체로 생성할 수 있다. 공간이 부족해지면 Gabage Collector가 실행된다.

 

 

  • Permanent Generation

영구적 세대. 객체가 생성되면 객체의 주소값이 생성된다. 그 주소값이 저장된 공간이다. Class Loader에 의해 로드되는 클래스, 메서드 등에 대한 메타 정보(정보에 대한 정보)가 저장되는 영역이고 JVM에 의해 사용된다. Reflection을 사용하여 동적으로 클래스가 로딩되는 경우에 사용된다. Reflection이란 객체를 통해 클래스의 정보를 분석해 내는 프로그래밍 기법으로 구체적인 클래스 타입을 알지 못해도, 컴파일된 바이트 코드를 통해 역으로 클래스의 정보를 알아내어 사용할 수 있다는 기법이다.

 

  •  New/Young Generation

이곳의 인스턴스들은 추후 Garbage Collector에 의해 사라진다. 생명 주기가 짧은 "젊은 객체"를 GC 대상으로 하는 영역이다. 여기서 일어나는 가비지 콜렉트를 Minor GC라고 한다. Eden은 객체들이 최초로 생성되는 공간이며, Suvivor0/1은 Eden에서 참조되는 객체들이 저장되는 공간이다. Eden 영역에 객체가 가득 차게 되면 첫 번째 가비지 콜렉트가 발생한다. DEden 영역에 있는 값들을 Suvivor 1 영역에 복사하고 이 영역을 제외한 나머지 객체를 삭제한다.

 

  • Tenured Generation

"Tenured"는 "종신"이란 뜻이다. New/Young Genreation에서 일정시간 참조되고, 살아남은 객체들이 저장되는 공간이다.  이곳의 인스턴스들은 추후 Garbage Collector에 의해 사라진다. 생명 주기가 긴 "오래된 객체"를 GC 대상으로 하는 영역이다. 여기서 일어나는 가비지 콜렉트를 Major GC라고 한다. Minor GC에 비해 속도가 느리다. 

 

Stack Area

각 스레드마다 하나씩 생성된다. 프로그램 실행 과정에서 임시로 할당되었다가 메서드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역이다. 각종 형태의 변수나 임시 데이터, 스레드나 메서드 정보를 저장한다. 메서드 호출 시마다 각각의 스택 프레임(그 메서드만을 위한 공간)이 생성된다. 메서드 수행이 끝나면 가장 마지막으로 들어왔던 프레임부터 차례로 삭제된다.(LIFO; Last-In-First-Out) 메서드 안에서 사용되는 값들을 저장한다. 또 호출된 메서드의 매개 변수, 지역 변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장한다.

 

PC Register

각 스레드마다 하나씩 생성된다. 스레드의 생성 동시에 생성되며, 스레드마다 하나씩 존재한다. 스레드가 수행할 다음 명령의 주소를 일시적으로 저장하는 데 사용된다.

 

Native Method Stack

각 스레드마다 하나씩 생성된다. 자바 프로그램이 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역. 다른 언어(C/C++ 등)의 메서드 호출을 위해 할당되는 구연 언어에 맞게 Stack이 형성되는 구역이다. JNI(Java Native Interface)라는 표준 규약을 제공한다. 일반 프로그램처럼 커널이 스택을 잡아 독자적으로 프로그램을 실행시키는 영역이다.

 

JVM: 아마 JNI(Java Native Interface)가 궁금할 수도 있을 것 같구나. JVI란 위의 글 내용으로 유추할 수 있듯이 다른 언어들로 작성된 라이브러리들을 호출하거나 반대로 호출되는 것을 가능케 하는 프로그래밍 프레임워크란다. 어떤 하드웨어는 자바만으로 처리가 힘들 수 있고, 자바로 다시 작성하기보단 대신 C나 C++로 이미 작성된 기존 라이브러리를 재사용하기 원할 수도 있단다. 그래서 다른 언어와 자바 간에 연결 다리가 되어줄 수 있는 것이 바로 JNI란다. 알겠니?

 

까비: 그.렇.습.니.다.

 

JVM: 음... 왠지 이해가 안 된 것 같은데 뭐 일단 넘어가자꾸나. 처음에 했던 질문이 기억나니 까비야?

 

까비: 자바가 컴파일러 언어인지 인터프리터 언어인지 말이에요?

 

JVM: 그래! 그럼 나는 무슨 언어일 것 같니?

 

까비: 음... 둘 다...?

 

JVM: 정답이란다! 나는 컴파일러와 인터프리터를 모두 사용하기 때문에 컴파일러 언어, 인터프리터 언어로 명확하게 분류되지는 않는단다. 그래서 종종 하이브리드 언어라고도 불리고 있지.

 

까비: 하이브리드... 뭔가 멋있어 보이네요.

 

JVM: 그렇단다! 그럼 나의 장점과 단점을 알아보도록 할까?

 

JVM의 장단점

 

JVM의 장점

  • 더보기
    1. 이식성: JVM은 플랫폼에 독립적이므로, 한 번 작성한 자바 프로그램은 여러 운영체제 와 장치에서 실행될 수 있다. JVM은 특정 운영체제에 종속되지 않고 중간 계층으로서 작동하기 때문에, 자바 프로그램은 운영체제에 구애받지 않고 이식성을 갖는다.
  • 더보기
    2. 메모리 관리: JVM은 가비지 컬렉션(Garbage Collection)을 통해 자동으로 메모리를 관리한다. 개발자는 메모리 할당과 해제를 명시적으로 다룰 필요가 없으며, 메모리 누수와 같은 문제를 줄일 수 있다.
  • 더보기
    3. 보안: JVM은 자바 프로그램을 보호하는 여러 가지 보안 기능을 제공한다. 바이트 코드의 검증, 클래스 로딩 시 보안 검사, 액세스 제어 등의 기능을 통해 안전한 실행 환경을 제공한다.
  • 더보기
    4. 동적 로딩: JVM은 동적 클래스 로딩을 지원한다. 이를 통해 프로그램이 실행 중에 필요한 클래스를 동적으로 로드하고 사용할 수 있다. 이는 유연성과 확장성을 높여준다.

JVM의 단점

  • 더보기
    1. 실행 속도: JVM은 인터프리터와 JIT 컴파일러를 사용하여 .java 바이트 코드를 기계어로 변환한다. 이러한 변환 과정은 초기 실행  시간이 필요하며, 일부 언어와 비교하여 상대적으로 실행 속도가 느릴 수 있다. 그러나 최적화된 JIT 컴파일러를 사용하면 이러한 성능 문제를 상당 부분 해결할 수 있다.
  • 더보기
    2. 메모리 사용량: JVM은 자체적인 메모리 사용량이 상대적으로 크다. JVM 자체의 오버헤드 및 가비지 컬렉션 작업에 필요한 추가적인 메모리를 사용하기 때문에, 자원이 제한적인 환경에서는 부담이 될 수 있다.
  • 더보기
    3. 시작 시간: JVM은 초기화 및 클래스 로딩 등의 작업이 필요하므로, 프로그램의 시작 시간이 상대적으로 오래 걸릴 수 있다. 특히 작은 규모의 애플리케이션의 경우, 이러한 시작 시간이 부담될 수 있다.
  • 더보기
    4. 리소스 관리: 가비지 컬렉션은 자동으로 메모리를 관리하지만, 이로 인해 일시적인 정지나 실행 속도 저하가 발생할 수 있다. 특히 대규모 및 실시간 시스템에서는 이러한 리소스가 중요한 고려 사항이 될 수 있다. 

 

까비: 아저씨는 장점도 많지만 단점도 많군요!

 

JVM: 허허. 이 녀석! 나는 물론 단점도 있지만 사람들이 많이 쓰는 이유는 그보다도 좋은 장점이 있기 때문이지.

 

까비: 그런 것 같아요!

 

JVM: 자 그럼 마지막으로 나를 도와주는 친구들을 소개하지. 바로 JRE와 JDK란다.

 

JVM, JRE, JDK

앞서 본문에선 자바의 핵심 기술은 JVM이라는 것을 알았다. 그렇다면 이 JVM을 우리가 쓰기 위해 추가적으로 필요한 장치는 무엇일까?

 

JRE

JRE(Java Runtime Environment) 는 JVM, 자바 클래스 라이브러리(Java class library), 자바 명령어(Java command) 및 기타 인프라를 포함한 컴파일된 Java 프로그램을 실행하는데 필요한 패키지이다.

 

JRE에는 다음과 같은 폴더가 포함된다.

  • bin/ : Java 실행 프로그램이 포함되어 있다. 
  • conf/ : 사용자 편집을 위한 구성 파일을 가진다.
  • lib/ : 여러 종류의 보조파일들이 있다. ( .jar, configuration file, property file, fonts, translations, certs 등) 가장 중요한 파일은 자바 표준 라이브러리에 해당하는 .class 파일을 포함한 modules이다.

 

JDK

JDK(Java Development Kit)는 Java를 사용하기 위해 필요한 모든 기능을 갖춘 Java SDK(Software Development Kit)이다. JRE의 기능에 더해 컴파일러(javac)와 jdb, javadoc과 같은 도구도 있다. 따라서 JDK는 프로그램을 생성하고 컴파일할 수 있다.

 

Java로 프로그래밍을 하지 않더라도 JDK를 설치해야 하는 경우가 있다. 예를 들어 JSP를 사용하여 웹 애플리케이션을 배포하는 경우 기술적으로는 어플리케이션 서버 내에서 Java 프로그램을 실행하는 것이므로 JDK가 필요하다. 어플리케이션 서버는 JSP를 Java 서블릿으로 변환하고 JDK를 사용하여 서블릿을 컴파일해야 하기 때문이다.

 

까비: JSP와 서블릿이 뭔가요?

 

JVM: JSP와 서블릿에 대한 개념은 나중에 스프링 부트를 공부할 때 자세히 배울 것이니 여기선 둘 다 일시적인 웹페이지를 만들어주는 도구라고만 생각해 두려무나.

 

까비: 음 잘 모르겠어요...

 

JVM: 괜찮단다. 여기선 일단 넘어가자꾸나! 아래는 JVM, JRE, JDK의 관계를 설명해 주는 그림이니 잘 봐두거라.

 

 

까비: JVM, JRE, JDK의 관계과 한눈에 들어와요!

 

JVM: 그렇지? 오늘 수업은 여기 까지란다! 다음에 또 보자꾸나. 

 

까비: 네 할아버지! 안녕히 계세요!

 

 

 

 

참고

https://pienguin.tistory.com

 

[JAVA] 자바 프로그램 실행 과정 및 기본 구조

1. 자바 프로그램 실행 과정 1.1. JVM 2. 자바의 기본 구조 3. 자바 프로그램 분석 1. 자바 프로그램 실행 과정 Java언어로 프로그래밍된 파일을 Java컴파일러가 가상 기계어 파일인 Java클래스 파일로

pienguin.tistory.com

https://velog.io/@pond1029/JVM

 

자바의 실행 과정

자바 기본 시리즈 JVM

velog.io

 

https://kingofbackend.tistory.com/123

 

[Java] 자바의 동작과정 Java Compiler와 JVM

이클립스에서 *.java를 단축키 눌러서 실행시킬 줄만 알았지 *.java 파일이 어떠한 과정을 거쳐 실행이 되는지는 알지 못했습니다. 따라서 자바 컴파일러는 어떤 역할을 수행하며, 어디서 많이 들

kingofbackend.tistory.com

 

https://jhyonhyon.tistory.com/18

 

[언어] 컴파일러(Compiler)와 인터프리터(Interpreter)

배경설명 코드를 작성하는 이유는 결국 그 코드를 실행했을 때 컴퓨터가 코드에 쓰인대로 행동하도록 하기 위해서겠죠! 하지만 컴퓨터의 뇌인 CPU는 사람이 사용하는 개발언어(C, C++, Java, Python

jhyonhyon.tistory.com

 

https://wonsjung.tistory.com/574

 

JVM이란? (Java Virtual Machine) JVM의 구조와 장점, 단점

▶ JVM (Java Virtual Machine) JVM은 'Java Virtual Machine'을 줄인 것으로 직역하면 '자바를 실행하기 위한 가상 기계'라고 할 수 있다. 자바로 작성된 애플리케이션은 모두 이 JVM에서만 실행되기 때문에, 자

wonsjung.tistory.com

 

https://doozi0316.tistory.com

 

[JAVA] JVM이란? 개념 및 구조 (JDK, JRE, JIT, 가비지 콜렉터...)

JVM이란 무엇인가 Java Virtual Machine의 줄임말. 직역하면 '자바를 실행하기 위한 가상 기계(컴퓨터)'라고 할 수 있다. Java 는 OS에 종속적이지 않다는 특징을 가지고 있다. OS에 종속받지 않고 실행되

doozi0316.tistory.com

 

https://sunrise-min.tistory.com

 

컴파일 언어와 인터프리터 언어의 차이 | Java는 어떤 언어인가?

컴파일 언어 소스 코드를 기계어로 컴파일해서 실행파일을 만들어 실행하는 방식이다. 컴파일 언어는 원시코드(프로그래머가 작성한 소스코드)를 한 번에 기계어로 변환하여 실행 파일을 만든

sunrise-min.tistory.com

 

https://developerntraveler.tistory.com/49

 

[ Java ] JDK, JRE 차이점(JDK란? JRE란?)

JDK와 JRE의 차이? JRE란? JRE( Java Runtime Environment )는 자바 가상 머신( Java Virtual Machine ), 자바 클래스 라이브러리( Java class library ), 자바 명령( Java command ) 및 기타 인프라를 포함한 컴파일된 Java 프로

developerntraveler.tistory.com

 

https://velog.io/@hahan

 

정적타입 언어 vs 동적타입 언어

프로그래밍 언어는 보통 정적타입의 언어와 동적타입의 언어로 나뉘어진다. 이 두가지를 비교해서 정리하기 전에 먼저 언어에서의 타입은 무엇을 뜻하는지에 대해 알아보자. 프로그래밍 언어

velog.io