JVM

이번 포스팅에서는 지난 포스팅에 이어서 JVM에 대해서 알아보도록 하겠습니다😊 JVM은 Java를 이해하는데에 있어서 필연적으로 알아야 하는 개념이며 JVM과 관련된 개념들 또한 알아보도록 하겠습니다!

Category

  1. JVM
  2. What is byte code?
  3. what is JIT compiler?
  4. Progress of Compilation
  5. JDK
  6. Example Code
  7. Tip
  8. Summary
  9. Reference

JVM

    운영체제는 자바 프로그램을 바로 실행할 수 없습니다😂 이는 Javac가 소스코드(*.java)를 컴파일하게 되면 바이트 코드 파일(.class)이 생성되는데 이것은 완전한 기계어가 아니기 때문인데요!

    이에 이 바이트 코드를 읽고 번역할 수 있는 가상의 운영체제가 필요한데 이것이 JVM(Java virtual machine)입니다.

    JVM은 운영체제(linux, unix or MS windows)를 대신해서 자바 프로그램을 실행하는 가상의 운영체제 역할을 수행합니다. 운영체제별로 프로그램을 실행하고 관리하는 방법이 다르기 때문에 자바 프로그램을 별도로 개발하는 것보다 운영체제 위에 JVM을 두어사용하는 것인데요! 즉, javac가 컴파일하여 생긴 바이트 코드 파일을 받아 JVM이 기계어로 바꾸어 운영체제가 받게 되는 구조를 갖게되는 것입니다. 이 구조를 통해 모든 운영체제에서 동일한 실행결과가 나올 수 있게 되는데 이를 ‘Write once, run anywhere(WORA)’라고 표현합니다. 한 번 작성하면 어디서든 실행된다라는 의미이며 이것은 Java의 가장 큰 장점 중 하나입니다. 따라서 개발자는 운영체제와 상관없이 자바프로그램을 개발 할 수 있습니다😊

    하지만 바이트 코드는 모든 JVM에서 동일한 결과를 보장하지만, JVM은 운영체제에 종속적입니다. 즉, 자바 프로그램을 각각의 운영체제가 이해할 수 있는 기계어로 번역해서 실행해야 하기 때문에 JVM은 운영체제에 맞게 설치되어야만 합니다. 이 말은 바이트 코드는 하나지만 JVM에 의해서 번역되는 기계어는 운영체제에 따라서 달라지게 된다고 이해 할 수 있습니다. 예를 들어, MS windows에 설치해야할 JVM과 Linux에 설치해야할 JVM은 달라야하며 그 이유는 각각의 운영체제가 알아들을 수 있는 machine language로 바꿔주어야 하기 때문입니다.

    이에 Java는 한번의 컴파일링으로 실행 가능한 기계어가 만들어지지 않고 Javac를 통해 Java byte code로 변환되고 이 byte code가 JVM에 의해 기계어로 번역되어 2번의 과정을 걸치고 실행됩니다. 이러한 과정 때문에 C와 C++의 컴파일 단계에서 만들어지는 완전한 기계어보다는 속도가 느리지만 기계어로 빠르게 변환해주는 JVM 내부의 최적화된 JIT 컴파일러를 통해서 속도의 격차가 많이 줄어들고 있습니다.

    또한 JVM은 JRE(Java Runtime Environment) or JDK(Java Devlopment Kit)를 설치하면 자동적으로 설치되는데 전에 설명했던 것과 같은 이유로 JDK와 JRE가 운영체제 별로 다르게 제공됩니다.

What is byte code?

    JVM을 배우면서 Javac compiler가 .java source를 .class인 byte code로 변환시켜준다는 개념을 배웠습니다. 그럼 byte code는 무엇일까요?

    byte code란 전에 배웠듯이 class파일을 말하며 javac를 통해 compile된 파일을 의미합니다. javap -c를 사용하면 바이트 코드를 볼 수있고, op code 1개당 1바이트를 차지하여 바이트 코드라고 말합니다. 총 200여개의 명령어가 있는데 약 2^8(=256)개이기 때문에 1 바이트로 해당 명령어들을 표현할 수 있어 1바이트가 사용됩니다.

What is JIT compiler?

    JIT compilerJust in Time을 줄인 말로 바이트 코드를 기계어로 번역하는 compiler입니다. Java interpreter가 바이트 코드를 한줄 씩 기계어로 번역을 할 때, 반복되는 코드(동일한 method)가 있다면 JIT compiler가 이를 컴파일해서 기계어로 변환하여 JVM 안에 있는 cache에 저장(caching)해놓고 재사용합니다. 이를 JIT compiler가 Hot Spot Detection하여 caching하여 사용한다고 말합니다.

    이를 통해 Java interpreter가 Hot spot에 해당하는 코드를 한 줄씩 기계어로 해석할 필요 없이 바로 실행할 수 있어 속도가 빨라지게 됩니다. 이에 프로그램을 실행할 때, 인터프리터와 JIT compiler가 함께 동작하며 JIT는 JVM runtime area에 들어갑니다. 이 때문에 Java가 인터프리터 방식과 컴파일 방식을 둘 다 사용한다고 볼 수 있습니다.

Progress of Compilation

지금까지 알아본 컴파일 과정들을 정리해 보도록 하겠습니다🙂

① .java파일을 javac compiler가 읽어 byte code인 .class 파일로 변환

② 해당 class 파일을 JVM 안에 있는 Java interpreter가 한 줄씩 읽어가며 기계어로 변환하고 Hot Spot(반복되는 코드 및 동일한 method)의 경우, JIT compiler가 JVM runtime area 안에 있는 cache에 저장하여 재사용해서 변환

위와 같이 크게 2가지 단계로 분류 할 수 있으며, 아래 형태로도 표현할 수 있습니다!

assets 2021 02 27 1

JDK

자바 프로그램을 개발하기 위해서는 Java SE(standard edtion)의 구현체인 JDK(Java Development Kit)를 설치해야 합니다. Java SE의 구현체에는 JDK(Java Development Kit)와 Java Runtime Enviroment(자바 실행 환경, JRE)라는 두 가지 버전이 존재합니다.

JDK는 프로그램 개발에 필요한 ①JVM, ②라이브러리 API, ③컴파일러 등의 개발 도구가 포함되어 있고 JRE에는 프로그램 실행에 필요한 ①JVM, ②라이브러리 API만 포함되어 있습니다.

따라서 자바 프로그램을 개발하고자 하는 것이 아니고 이미 개발된 프로그램만 실행만한다면 JRE만 설치하면 된다고 합니다. 따라서 JDK = JRE + 개발에 필요한 도구(compiler) 이고 JRE = JVM + 표준 클래스 라이브러리라고 볼 수 있습니다.

아래의 그림은 JDK, JRE, JVM의 관계를 표현한 그림입니다.

assets 2021 02 27 2

Example Code

예시를 통해 어떻게 source code를 작성하고 실행하는지 살펴보겠습니다.

// Hello.java
public class Hello{
	public static void main(String[] args){
		System.out.println("Hello, welcome to the java world!:");
	}
}

Java source code는 반드시 class block과 method block으로 구성되어야 합니다. method block은 단독으로 작성될 수 없고 항상 class block 내부에 작성되어야 합니다. method와 class의 개발자가 규칙을 지키는 한에서 마음대로 정할 수 있지만 main() method만큼은 다른 이름으로 바꿀 수 없습니다. 그 이유는 java.exe(java command)로 JVM을 구동시키면 제일 먼저 main()메소드를 찾아서 실행시키기 때문인데요! 이 때문에 main() method를 프로그램 실행의 진입점이라고 합니다. 만약 클래스 내부에 main() method가 없거나 잘못 작성하게되면 클래스를 실행할 수 없게되어 error가 발합니다.

아래는 위의 Hello.java를 실행시키기 위한 2개의 command 입니다.

// java(source) -> class(Java byte code)
javac *.java

// class(Java bye code) -> machine language
java *

Tip

  • 컴파일러는 세미콜론이 나올 때 까지 실행문이 계속해서 연결된 것으로 보기 때문에 한 실행문이 여러줄에 걸쳐 있어도 되고 한 줄에 여러개의 실행문이 있어도 됩니다.
int x = 1; int y = 2;
int result =
x + y;
System.out.println(result);
  • IDE(Integrated Development Environments)란 통합 개발 환경을 의미하며 이클립스는 자바 프로그램을 개발하기 위한 통합 개발 환경입니다.

Summary

  1. JVM은 가상 운영 체제 역할을 하며 javac가 만들어낸 바이트 코드를 기계어로 번역합니다.
  2. JVM은 기계어로 번역할 때, JIT compiler와 Java interpreter가 사용되며 JIT compiler는 Hot spot detection을 통해 컴파일 해놓은 기계어들을 JVM내에 caching하여 사용하기 때문에 속도를 더욱 빠르게 해줍니다.
  3. java.exe(java command)를 통해 JVM이 구동됩니다.
  4. Java를 개발하기 위해선 JDK가 필요하지만 실행시키기 위해선 JRE만 있어도 됩니다.
  5. JVM은 운영체제별로 다르게 설치해야하지만 설치해 놓으면 모든 운영체제에서 Java를 통한 개발이 가능합니다. 이를 ‘WORA’라고 합니다.

이것으로 JRM 포스트를 마치도록 하겠습니다. 감사합니다😎

Reference


Written by@[Gunu]
AI, 수학에 관심이 많은 대학생입니다😊

GitHub