기능 구현보다 이 기능을 어떻게 구현해야 더 좋은 구현이 될까를 고민하는 지금 Java 프로그램을 실행하는 JVM을 알아야 좋은 구현을 진행할 것이라는 생각이 들었다. 따라서, JVM을 공부해보려고 한다.
JDK(Java Development Kit)와 JRE(Java Runtime Environment)
JVM을 공부하는데 왜 JDK와 JRE가 나올까?
이는 JDK와 JRE에 JVM이 포함되어 있고, Java를 개발하기 위해선 단순히 JDK 안에 있는 `javac`(컴파일러)가 필요하기 때문이다. 또, JVM은 혼자서 돌아가지 못하며, `String`, `System`, `ArrayList` 같은 기본 클래스 파일들이 있어야 코드를 실행할 수 있는데, 이 파일들이 바로 JRE에 들어있기 때문이다. JVM이 클래스 로더를 통해 이 파일들을 어떻게 읽어오는지 알아야 한다.
JRE
JRE는 "자바 애플리케이션을 실행하기 위해 필요한 최소한의 환경"이다. 개발 관련 도구는 없고, 오직 실행만을 목적으로 한다.
JRE의 구성 요소
JVM
자바 표준 라이브러리(java.lang, java.util…)
런타임 지원 파일
java 명령어 - JVM 런처
JVM
자바 바이트코드(.class)를 운영체제(OS)가 이해할 수 있는 기계어로 통역하고 실행하는 엔진이다.
자바 표준 라이브러리
JVM이 코드를 실행하다가 `System.out.println()`이나 `ArrayList`, `Thread`등을 만나면, 이 기능들이 정의된 실제 파일이 필요하다. JRE는 이 표준 클래스 파일들(API)을 묶어서 가지고 있다.
런타임 지원 파일
JVM이 실행되는 동안 필요한 데이터 파일들이다.
lib/
├── tzdb.dat # 타임존 데이터
│ → ZonedDateTime, ZoneId 등에서 사용
├── currency.data # 통화 정보
│ → Currency.getInstance() 등에서 사용
├── charsets.jar # 문자 인코딩
│ → UTF-8, EUC-KR 등 변환
└── security/
└── java.policy # 보안 정책
→ SecurityManager에서 사용
java 명령어 (JVM 런처)
JVM을 시작하고 애플리케이션을 실행하는 프로그램이다. JVM 프로세스 생성, 클래스패스 설정, JVM 옵션 전달 (`-Xmx`, `-XX:+UseG1GC` 등), `main()` 메서드 찾아서 실행하는 역할을 한다.
💡JVM은 혼자서 작동할 수 있을까? 아니다. System.class가 없으면 `System.out.println()`을 실행할 수 없고, java 명령어가 없으면 JVM을 시작할 수 없다. 또, 런타임 지원 파일들(타임존 데이터, 문자 인코딩 등)이 없다면 실행할 수 없다. 따라서 'JRE = JVM + 실행에 필요한 모든 것'으로 볼 수 있다.
JDK
JDK는 "자바 애플리케이션을 개발하기 위한 도구 모음"이다. JRE가 "실행"에 집중한다면, JDK는 "개발"에 필요한 모든 것을 포함한다. JDK를 설치하면 JRE가 포함되어 있으므로 실행도 당연히 가능하다.
즉, 'JDK = JRE + 개발 도구'이다.
JDK의 구성 요소
JRE
javac - 자바 컴파일러
java - JVM 런처
javadoc - API 문서 생성
jar - JAR 파일 생성/관리
jdb - 디버거
javac
사람이 작성한 코드(.java)를 JVM이 이해할 수 있는 바이트코드(.class)로 변환한다.
실제로 하는 일:
문법 검사(Syntax Check): 괄호, 세미콜론 등 문법 오류 검출
타입 검사(Type Check): 타입 불일치, 제네릭 오류 검출
바이트코드 생성: JVM이 실행 가능한 중간 언어로 변환
최적화: 상수 폴딩, 데드 코드 제거 등
# 사용 예시
# Case 1: 단일 클래스 파일 실행 (학습/테스트)
javac HelloWorld.java # 먼저 컴파일
java HelloWorld # 그 다음 실행
# Case 2: JAR 파일 실행 (배포된 애플리케이션)
java -jar myapp.jar
# Case 3: 클래스패스 지정 (외부 라이브러리 사용)
java -cp target/classes:lib/* com.example.Main
# Case 4: JVM 옵션 + JAR 실행 (운영 서버)
java -Xms512m -Xmx2g -XX:+UseG1GC -jar app.jar
IntelliJ나 Eclipse에서 코드를 저장하면 자동으로 컴파일되는데, 이때 IDE가 백그라운드에서 `javac`를 호출하고 있다. "Auto Build" 기능이 꺼져있으면 수동으로 컴파일해야 하는데, 이 경우 저장했는데도 변경사항이 반영 안 되는 것처럼 보일 수 있다. (IDE의 빨간 밑줄이 바로 javac의 검사 결과)
💡javac가 중요한 이유 1. 컴파일 타임에 오류를 잡아줌 ➡️ 런타임 에러 방지 2. 바이트코드 최적화로 실행 성능 향상
java
JVM을 시작하고 컴파일된 `.class`파일을 로딩하여 애플리케이션을 시작한다. `main()`메서드를 찾아 호출하는 시작점이다.
💡JDK의 java vs JRE의 java JRE에도 JVM을 시작하는 java가 있다. 서로 무슨 차이가 있을까? 사실 없다. 마침 jdk1.8버전이 있어서 확인해봤다.JDK의 javaJRE의 java