☕Java — 자바 실행 원리 훑기
Java 실행환경, 컴파일 과정, 메모리 구조, 기본형/참조형
•
#java
1. JVM / JRE / JDK
JVM (Java Virtual Machine)
JVM은 자바 바이트코드를 실행하는 가상 머신이다. 운영체제 위에서 동작하며, 자바 프로그램이 OS에 독립적으로 실행될 수 있게 해준다.
- 바이트코드를 읽어 기계어로 변환하고 실행
- 메모리 관리(가비지 컬렉션) 담당
- OS별로 JVM 구현체가 다르지만 바이트코드는 동일하게 동작
JRE (Java Runtime Environment)
JRE는 자바 프로그램을 실행하기 위한 환경이다.
- JVM + 자바 표준 라이브러리(클래스 파일들)로 구성
- 실행만 할 때 필요 (개발 도구 미포함)
JDK (Java Development Kit)
JDK는 자바 프로그램을 개발하기 위한 키트다.
- JRE + 컴파일러(
javac), 디버거 등 개발 도구 포함 - 개발자는 반드시 JDK가 필요
JDK └── JRE └── JVM
2. 자바 컴파일 과정과 바이트코드
자바는 두 단계를 거쳐 실행된다.
소스코드(.java) → [javac 컴파일러] → 바이트코드(.class) → [JVM] → 실행
- 소스코드 작성:
.java파일에 자바 코드 작성 - 컴파일:
javac가 소스코드를 바이트코드로 변환 →.class파일 생성 - 실행: JVM이
.class파일을 읽어 OS에 맞는 기계어로 변환하고 실행
바이트코드란?
바이트코드는 JVM이 이해할 수 있는 중간 언어다. 특정 OS나 CPU에 종속되지 않기 때문에 "Write Once, Run Anywhere" 가 가능하다. 윈도우에서 컴파일한 .class 파일을 리눅스 JVM에서도 그대로 실행할 수 있다.
3. 자바 메모리 구조
JVM은 실행 시 메모리를 크게 5가지 영역으로 나눠 관리한다.
| 영역 | 설명 |
|---|---|
| 메서드(Method) 영역 | 클래스 정보, static 변수, 상수 등 저장. JVM 시작 시 생성 |
| 힙(Heap) 영역 | new로 생성된 객체와 배열이 저장됨. GC가 관리 |
| 스택(Stack) 영역 | 메서드 호출 시 생성되는 프레임. 지역변수, 매개변수 저장 |
| PC 레지스터 | 현재 실행 중인 JVM 명령어 주소 저장 |
| 네이티브 메서드 스택 | C/C++ 등 네이티브 코드 실행 시 사용 |
┌─────────────────────────────────┐ │ 메서드(Method) 영역 │ ← 클래스 정보, static ├─────────────────────────────────┤ │ 힙(Heap) │ ← 객체, 배열 (GC 대상) ├─────────┬───────────┬───────────┤ │ 스택 │ 스택 │ 스택 │ ← 스레드마다 별도 생성 │(Thread1)│(Thread2) │(Thread3) │ └─────────┴───────────────────────┘
4. 기본형(Primitive) vs 참조형(Reference)
기본형 (Primitive Type)
값 자체를 스택에 직접 저장한다. 총 8가지
| 종류 | 타입 | 크기 | 기본값 |
|---|---|---|---|
| 정수 | byte | 1byte | 0 |
| 정수 | short | 2byte | 0 |
| 정수 | int | 4byte | 0 |
| 정수 | long | 8byte | 0L |
| 실수 | float | 4byte | 0.0f |
| 실수 | double | 8byte | 0.0 |
| 문자 | char | 2byte | '�' |
| 논리 | boolean | 1byte | false |
int a = 10; // 스택에 10이라는 값 자체가 저장 int b = a; // b는 a의 값을 복사 → 독립적인 변수 b = 20; // a는 여전히 10
참조형 (Reference Type)
객체는 힙에 저장되고 스택에는 그 객체의 주소(참조값) 만 저장된다.
String s1 = new String("hello"); // 힙에 객체 생성, 스택엔 주소 저장 String s2 = s1; // s2도 같은 객체를 가리킴
스택 힙 ┌──────┐ ┌───────────────┐ │ s1 │ ──────→ │ "hello" 객체 │ ├──────┤ └───────────────┘ │ s2 │ ──────↗ └──────┘
기본형은 값 비교에
==를 쓰면 되지만, 참조형은==가 주소를 비교하므로 내용 비교에는.equals()를 사용해야 한다.
Wrapper 클래스
기본형을 객체로 다뤄야 할 때(제네릭, 컬렉션 등) Wrapper 클래스를 사용한다.
| 기본형 | Wrapper |
|---|---|
int | Integer |
double | Double |
boolean | Boolean |
char | Character |
자바는 기본형과 Wrapper 간 변환을 오토박싱/언박싱으로 자동 처리한다.
Integer num = 42; // 오토박싱: int → Integer int n = num; // 언박싱: Integer → int