목표
자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기.
학습할 것
- JVM이란 무엇인가
- 컴파일 하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는지
- JVM 구성 요소
- JDK와 JRE의 차이
JVM이란 무엇인가
JVM(Java Vertual Machine)은 운영 체제와 자바 바이트코드(Java Bytecode)의 사이에서 자바 바이트코드를 해석해 모든 운영 체제에서 동일하게 동작하도록 하는 가상 머신이며, OS별로 각각 제공되는 JVM이 자바 바이트코드를 기계어로 해석해 동작하도록 해줍니다.
때문에 우리가 작성하는 자바 프로그램은 OS에 상관없이 JVM만 설치되있다면 동일한 코드로 동일한 동작을 할 수 있는 것입니다.
JVM의 구조
Class Loader
- Class Loader는 이름 그대로 *.class 파일을 로드하는데 사용됩니다.
- Class Loader에서 *.class 파일을 로드하는 과정에서 Bytecode 검증을 수행하며, 유효한 *.class 파일만 로드가됩니다.
- Bytecode 검증 과정에서 프로그램을 수행하는 Java 버전보다 프로그램이 작성된 Java 버전이 높다면 java.lang.UnsupportedClassVersionError 예외가 발생합니다. 각 Java 버전별로 바이트코드가 다르게 컴파일되기 때문입니다.
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: hello has been compiled by a more recent version of the Java Runtime (class file version 56.0), this version of the Java Runtime only recognizes class file versions up to 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Runtime Data Areas
Runtime Data Areas는 자바 프로그램을 실행하기 위해 OS로부터 할당받은 공간이며, 아래와 같이 구성되어있습니다.
- Method Area
- 클래스, 인터페이스, 메서드, 필드 등의 바이트코드를 보관합니다. - Heap
- 프로그램에서 동적으로 생성한 Instance가 저장되는 영역입니다.
- 예를 들어, Object obj = new Object(); 코드 수행 시, obj 인스턴스가 이 영역에 저장됩니다. - Java Threads
- 메서드가 호출되면 이 영역에 메서드와 메서드 정보가 쌓이고, 메서드가 종료되면 제거됩니다. - Program Counter Registers
- 현재 수행중인 JVM Instruction 주소를 갖습니다. - Native Internal Threads
- 자바 외의 언어로 작성된 네이티브 코드를 위한 영역입니다.
- 예를 들어, 윈도우 상에서 JVM이 실행중인 경우 이 영역에는 윈도우 네이티브 코드를, 리눅스 상에서 JVM이 실행중인 경우 리눅스 네이티브 코드를 위한 메모리 공간을 갖습니다.
Execution Engine
- 로드된 *.class의 바이트코드를 실행하는 역할을 합니다.
- JIT 컴파일러와 인터프리터, Garbage Collector가 이 영역에 포함되어있습니다.
컴파일 하는 방법
기본적인 방법은 *.java 파일을 작성해 javac 명령어로 컴파일 하는 방법입니다.
우선, Hello, World! 라는 문자열을 출력하는 코드를 작성해보았습니다.
public class HelloWorld
{
public static void main (String[] args)
{
System.out.println("Hello, World!");
}
}
그리고 javac 파일명.java 명령어로 컴파일해줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1hoon@bag-ilhun-ui-MacBookPro temp % ls -al
total 8
drwxr-xr-x 3 1hoon staff 96 11 15 19:40 .
drwx------@ 16 1hoon staff 512 11 15 19:39 ..
-rw-r--r-- 1 1hoon staff 130 11 15 19:40 HelloWorld.java
1hoon@bag-ilhun-ui-MacBookPro temp % javac HelloWorld.java
1hoon@bag-ilhun-ui-MacBookPro temp % ls -al
total 16
drwxr-xr-x 4 1hoon staff 128 11 15 19:41 .
drwx------@ 16 1hoon staff 512 11 15 19:39 ..
-rw-r--r-- 1 1hoon staff 427 11 15 19:41 HelloWorld.class
-rw-r--r-- 1 1hoon staff 130 11 15 19:40 HelloWorld.java
1hoon@bag-ilhun-ui-MacBookPro temp %
|
cs |
위처럼, 컴파일이 완료되면 동일한 이름을 가진 *.class 파일이 컴파일되어 생성됩니다.
실행하는 방법
앞서 컴파일한 HelloWorld 클래스를 실행해보겠습니다.
컴파일한 *.class 파일이 있는 디렉터리로 이동해 java 클래스명 명령어를 실행해줍니다.
1
2
|
1hoon@bag-ilhun-ui-MacBookPro temp % java HelloWorld
Hello, World!
|
cs |
바이트코드란 무엇인가
- 바이트코드는 우리가 작성한 프로그램을 JVM이 이해할 수 있는 언어로 변환된 코드를 의미합니다.
- 코드의 명령어 크기가 1Byte이기 때문에 자바 바이트코드 라고 불립니다.
- 프로그램 코드(*.java) -> 바이트코드(*.class) -> 기계어
- 이러한 바이트코드는 자바 디컴파일러(예: JD GUI)로 디컴파일해 *.java 코드로 만들 수 있습니다.
JIT 컴파일러란 무엇이며 어떻게 동작하는가
JIT(Just In Time) 컴파일러는 프로그램을 실제 실행하는 시점에 기계어로 변환하는 컴파일러입니다. 컴파일과 인터프리트 두 가지 방식을 혼합해 실행 시점에서는 인터프리터와 같이 기계어 코드를 생성하고, 해당 코드가 컴파일 대상이 되면 컴파일 후 그 코드를 캐싱합니다.
JDK와 JRE의 차이
JRE
- 자바 런타임 환경(Java Runtime Environment)
- Java로 작성된 프로그램을 실행하기위한 라이브러리입니다.
- JVM과 코어 라이브러리를 제공합니다.
JDK
- 자바 개발 키트(Java Development Kit)
- Java 프로그램을 개발하기 위한 번들입니다.
- JRE에 Java Compiler와 디버거같은 도구가 추가적으로 포함되어있습니다.
'☕️ JAVA > WhiteShip Java LIVE Study' 카테고리의 다른 글
[WhiteShip Java LIVE Study] 6주차 : 상속 (0) | 2021.02.17 |
---|---|
[WhiteShip Java LIVE Study] 5주차 : 클래스 (2) | 2020.12.25 |
[WhiteShip Java LIVE Study] 4주차 : 제어문 (0) | 2020.12.11 |
[WhiteShip Java LIVE Study] 3주차 : 연산자 (0) | 2020.11.30 |
[WhiteShip Java LIVE Study] 2주차 : 자바 데이터 타입, 변수 그리고 배열 (0) | 2020.11.20 |