자바 소스 파일 (.java)를 JVM으로 실행하는 과정 이해하기
학습할 내용은 다음과 같습니다.
- JVM이란 무엇인가
- 컴파일 하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는지
- JVM 구성 요소
- JDK와 JRE의 차이
Reference: Java in a Nutshell
자바 가상머신으로 자바 바이트코드(.class)를 자바 실행코드로 변환해서 실행합니다.
자바로 작성한 모든 프로그램은 자바 가상 머신에서 실행될 수 있습니다. 따라서 JVM은 반드시 필요합니다.
JVM은 운영체제 위에서 동작하는데 서로 다른 운영체제를 가지고 있더라도 JVM만 설치되어 있다면 같은 자바 프로그램은 아무런 문제없이 동작하는게 가능합니다. 그렇기 때문에 개발자는 단 하나의 프로그램만 배포하면 됩니다.
하지만 자바 가상 머신은 운영체제에 종속적이기 때문에 각 운영체제에 맞는 자바 가상머신을 설치해야합니다
그리고 일반 프로그램은 자바 가상 머신이라는 한 단계를 더 거쳐야하기 떄문에 실행속도가 느리다는 단점이 있습니다.
바이트 코드를 JIT or 인터프리터로 실행을 해서 OS에 맞는 기계어로 변환되서 실행합니다.
JVM은 홀로 배포되지 않고 JRE (Java Runtime Environment) 형식으로 배포됩니다.
컴파일된 .class 파일을 “java”명령어를 사용하여 실행할 수 있습니다.
실행 명령어는 다음과 같습니다. 실행할 때는 java명령어를 사용하고, 파일 확장자(.class)를 뺀 클래스 이름만 써주면 됩니다.
자바 바이트코드는 자바 컴파일러에 의해 바이트코드로 변환됩니다.
자바 바이트 코드(.class 파일)란 JVM이 이해할 수 있는 언어로 변환된 자바 소스 코드를 말합니다.
자바 컴파일러에 의해 변환된 코드의 명령어 크기가 1바이트라서 자바 바이트 코드라고 불리고 있습니다.
// 아래와 같은 자바 코드가 있다고 생각해봅시다.
for (int i = 2; i < 1000; i++) {
for (int j = 2; j < i; j++) {
if (i % j == 0)
continue outer;
}
System.out.println (i);
}
// 자바 컴파일러는 은 이 자바 코드를 바이트 코드로 변환합니다.
0: iconst_2
1: istore_1
2: iload_1
3: sipush 1000
6: if_icmpge 44
9: iconst_2
10: istore_2
11: iload_2
12: iload_1
13: if_icmpge 31
16: iload_1
17: iload_2
18: irem
19: ifne 25
22: goto 38
25: iinc 2, 1
28: goto 11
31: getstatic #84; // Field java/lang/System.out:Ljava/io/PrintStream;
34: iload_1
35: invokevirtual #85; // Method java/io/PrintStream.println:(I)V
38: iinc 1, 1
41: goto 2
44: return
자바 컴파일러가 생성한 자바 바이트 코드를 런타임에 바로 기계어로 변환하는 역할을 합니다
프로그램을 실행 시점에 기게어로 변환해주는 컴파일러를 말합니다
이 방법은 Dynamic translation이라고 불리고 프로그램의 실행 속도를 향상시키기 위해 개발되었습니다.
전통적인 방식에서 프로그램을 실행시키는 방법은 인터프리터 방식과 컴파일 방식이 있습니다.
JIT 컴파일은 두 가지의 방식을 혼합해서 사용합니다. 실행 시점에 인터프리트 방식으로 기계어를 생성하고 그 코드를 캐싱합니다. 그래서 같은 함수가 여러번 실행되면 캐싱된 코드를 가져와서 매번 같은 기계어가 생성되는 걸 방지합니다.
일반적인 인터프리터 언어는 바이트 코드나 소스코드 최적화 과정이 업기 때문에 성능이 낮습니다. 컴파일 하는 언어는 실행 전에 무조건 컴파일 해야하기 때문에 다양한 플랫폼에 맞게 컴파일 할려면 시간이 오래걸립니다. JVM에서 실행하는 JIT 컴파일러는 복잡한 최적화는 자바 컴파일러가 해줬기 때문에 고려하지 않아도 되고 바이트 코드 자체가 빠른 기계어로 변환을 목적으로 설계되었기 때문에 실행속도나 성능에서 우월합니다.
예전에 JVM에 대해 공부했던 글이 있습니다. 다음 글을 참고해주세요.
https://velog.io/@youngerjesus/JVM-JDK-JRE%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C
JRE (Java Runtime Environment)
JDK (Java Development Kit)
둘의 차이는 JDK는 Java 소프트웨어를 개발하는데 필요한 것들인 반면 JRE는 Java 애플리케이션을 프로그래밍하고 실행하는데 필요한 툴로 구성되어 있습니다.