☕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]  →  실행
  1. 소스코드 작성: .java 파일에 자바 코드 작성
  2. 컴파일: javac가 소스코드를 바이트코드로 변환 → .class 파일 생성
  3. 실행: 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가지

종류타입크기기본값
정수byte1byte0
정수short2byte0
정수int4byte0
정수long8byte0L
실수float4byte0.0f
실수double8byte0.0
문자char2byte'�'
논리boolean1bytefalse
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
intInteger
doubleDouble
booleanBoolean
charCharacter

자바는 기본형과 Wrapper 간 변환을 오토박싱/언박싱으로 자동 처리한다.

Integer num = 42; // 오토박싱: int → Integer int n = num; // 언박싱: Integer → int