2주차 자료의 모든 토픽을 "표면 → 깊이" 순서로 재배열한 학습 경로.
1주차에서 OOP·JVM·GC·컬렉션을 개론 으로 봤다면, 2주차는 동일 주제를 JVM 내부·바이트코드·메모리 매핑 수준으로 파고든다.
새로 등장하는 주제: Reflection, Iterator, 버퍼(Buffer).
[Phase 1] 자바 변수 ↔ 메모리 영역의 매핑
↓
[Phase 2] JVM 메서드 실행 메커니즘
↓
[Phase 3] 바이트코드와 상수 풀의 세계 ◄── 여기가 2주차의 정점
↓
[Phase 4] GC 심화 — G1 GC 들여다보기
↓
[Phase 5] 컬렉션 프레임워크 내부 구조
↓
[Phase 6] 동적 프로그래밍 — Reflection & Iterator
↓
[Phase 7] 보조 개념 — Buffer
총 7 Phase × 23 Unit — 각 Unit은 30분~1시간 분량.
| 1주차 (개론) | 2주차 (심화) |
|---|---|
| JVM 메모리 영역의 5분할 | Method Area의 3개 존 으로 더 쪼개기 |
| GC의 동작 원리 | G1 GC 리전 모델 과 정지시간 예측 |
| ArrayList vs LinkedList 비교 | 배열 확장 정책·노드 구조 코드로 검증 |
| (없음) | 바이트코드 읽기, Reflection, Iterator |
| Day | Phase | 학습 목표 |
|---|---|---|
| 1일차 | Phase 1 | 변수 3종류와 메모리 영역의 매핑 정복 |
| 2일차 | Phase 2 | 메서드 호출이 JVM 안에서 어떻게 일어나는지 |
| 3일차 | Phase 3 (전반) | 바이트코드 읽는 법 + 상수 풀 |
| 4일차 | Phase 3 (후반) | 심볼 참조와 new의 진실 |
| 5일차 | Phase 4 | G1 GC의 모든 것 |
| 6일차 | Phase 5 + 7 | 컬렉션 내부 + Buffer |
| 7일차 | Phase 6 | Reflection + Iterator |
목표: "이 변수는 메모리의 어디에 저장될까?"에 즉답할 수 있게 된다.
1주차에서는 Heap/Stack/Method Area를 큰 그림으로 봤다면, 여기선 변수 종류 ↔ 영역 매핑 을 손에 익힌다.
선수 지식: 1주차 Phase 2 (클래스/메서드)
핵심 개념
static 없이 클래스에 선언, 객체별로 존재static으로 선언, 클래스 단위 1개자기 점검
선수 지식: Unit 1.1
핵심 개념
| 변수 종류 | 저장 영역 | 생성 시점 | 소멸 시점 |
|---|---|---|---|
| 지역 변수 | Stack | 메서드 호출 | 메서드 종료 |
| 인스턴스 변수 | Heap (객체와 함께) | new 시점 | GC가 객체 회수 시 |
| 클래스 변수 | Method Area | 클래스 로딩 시 | JVM 종료 시 |
자기 점검
Member m = new Member() 에서 m(참조)과 Member 객체 본체의 저장 위치는?선수 지식: Unit 1.2
핵심 개념
Method Area
├─ Class Metadata Zone : 클래스명, 부모, 메서드 시그니처, 필드 선언 정보
├─ Static Zone : static 메서드/필드의 실제 바이트코드
└─ Non-Static Zone : 인스턴스 메서드의 실제 바이트코드
자기 점검
main() 이 Static Zone에 있는 이유는?선수 지식: Unit 1.2
핵심 개념
자기 점검
선수 지식: Unit 1.3, Unit 1.4
핵심 개념
new로 만든 모든 객체는 Heap에new 시점에 Heap의 객체 안에 함께 할당자기 점검
선수 지식: Unit 1.5
핵심 개념
"Hello world" 같은 리터럴은 한 번만 만들고 재사용자기 점검
String a = "abc"; String b = "abc"; 일 때 메모리에 String 객체는 몇 개 만들어지는가?목표: 메서드 호출 한 줄(
obj.method())이 JVM 안에서 실제로 어떤 단계를 거치는지 추적할 수 있다.
선수 지식: Phase 1 전체
핵심 개념
메서드 호출 시 JVM의 처리 순서:
1. Class Metadata Zone에서 메서드 시그니처 확인
2. Static Zone 또는 Non-Static Zone에서 실제 바이트코드 찾아서 실행
즉, "무엇을 호출하는가" 와 "실제 코드가 어디 있는가" 가 분리되어 있다.
자기 점검
선수 지식: Unit 2.1
핵심 개념
Model1.hap() → hap() 으로도 호출 가능)자기 점검
main() 안에서 인스턴스 메서드를 직접 호출할 수 없는 이유는?선수 지식: Unit 2.2
케이스: Model2 m2 = new Model2(); int sum = m2.hap(1, 2);
호출 과정 추적
1. JVM이 바이트코드 읽기 → Class Metadata, Static Zone, Non-Static Zone에 정보 적재
2. main() 실행 시작 (Static Zone)
3. new Model2() 만나면:
Model2() 생성자가 Stack에 호출 → 실행 → 제거m2로 main 스택 프레임에 저장m2.hap(1, 2):hap() 발견 → Stack에 호출 → 실행 → 제거자기 점검
선수 지식: Unit 2.3
핵심 개념
new Model2() 한 줄이 하는 4가지:
1. Class Metadata Zone에서 Model2 클래스 정보 찾기
2. Heap에 객체 메모리 공간 확보
3. 멤버변수 초기화 (있다면)
4. 생성자(Constructor) 호출
자기 점검
new 없이 객체를 만들 수 있는 방법은? (힌트: Reflection, clone, deserialization)목표:
.class파일을 직접 읽을 수 있게 된다. JVM이 클래스 정보를 어떻게 식별·관리하는지 본다.
선수 지식: Phase 2 전체
핵심 개념
.java → javac → .class (바이트코드)javap -c MyClass자기 점검
선수 지식: Unit 3.1
핵심 개념
#숫자 표기는 상수 풀 인덱스자기 점검
원본 자료: JVM 밑바닥까지 파헤치기, p.67
선수 지식: Unit 3.2
핵심 개념
#7 같은 인덱스 → 상수 풀에서 "어떤 심볼인가" 찾아냄예시: new 명령
4: new #7 // class org/example/CalHap#7 = 상수 풀의 7번 = org/example/CalHap 클래스 심볼자기 점검
원본 자료: JVM 밑바닥까지 파헤치기, p.67
선수 지식: Unit 3.3
예시 분석
public static void main(String[] args) {
int a=1, b=1;
CalHap ch = new CalHap(a, b);
ch.hap();
}
→ 바이트코드:
0: iconst_1 // a=1
1: istore_1
2: iconst_1 // b=1
3: istore_2
4: new #7 // new CalHap (#7은 상수 풀의 CalHap 클래스 참조)
7: dup // 스택의 객체 참조 복제
8: iload_1 // a를 스택에
9: iload_2 // b를 스택에
10: invokespecial #9 // 생성자 호출
13: astore_3 // ch에 저장
자기 점검
dup는 왜 필요한가? (힌트: 생성자 호출 후에도 ch에 저장할 객체 참조가 필요)invokespecial, invokevirtual, invokestatic의 차이는?목표: 1주차에서 이름만 봤던 G1 GC를 리전 모델·정지시간 예측 모델 까지 이해한다.
선수 지식: 1주차 Phase 5
핵심 개념
순환 참조 시나리오:
Root → A ⇄ B (A와 B가 서로 참조)
Root가 참조를 끊어도 A↔B의 카운터는 0이 안 됨 → 영원히 회수 안 됨 → 메모리 누수
자기 점검
원본 자료: JVM 밑바닥까지 파헤치기, p.94
선수 지식: Unit 4.1, 1주차 Phase 5
핵심 개념
자기 점검
선수 지식: Unit 4.2
핵심 개념
기존 GC vs G1:
[기존 GC]
┌─ Eden ──┬─ Survivor ──┬─── Old ───┐ ← 영역 크기 고정, 위치 고정
│ │ │ │
└─────────┴─────────────┴───────────┘
[G1 GC]
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│E│ │S│O│ │O│E│ │ │S│O│ │E│ ← 같은 크기의 리전, 역할은 동적으로 부여
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
-XX:G1HeapRegionSize 로 조절자기 점검
선수 지식: Unit 4.3
핵심 개념
자기 점검
선수 지식: Unit 4.4
핵심 개념
G1의 회수 기준:
1. 어느 리전에 쓰레기가 가장 많은가 (회수 가능 공간 크기)
2. 회수에 드는 시간이 얼마인가 (경험값으로 예측)
3. → 정지시간 한도 내에서 회수 효과가 큰 리전부터 처리
이게 G1의 이름의 유래: Garbage First (쓰레기 많은 곳 먼저)
자기 점검
목표: 1주차에 ArrayList vs LinkedList를 큰 그림으로 봤다면, 여기서는 배열 확장 정책·노드 연결 구조 를 코드로 검증한다.
선수 지식: 1주차 Phase 6
핵심 개념
| 자료구조 | 순서 | 중복 | 키-값 |
|---|---|---|---|
| List | ✅ 있음 | ✅ 허용 | ❌ |
| Set | ❌ 없음 | ❌ 불허 | ❌ |
| Map | ❌ 없음 | 키 ❌ / 값 ✅ | ✅ |
자기 점검
선수 지식: Unit 5.1
핵심 개념
자기 점검
new ArrayList<>(1000) 처럼 초기 크기를 지정하는 게 왜 효율적인가?원본 자료: 자바의신 2 + 컬렉션 내부 분석
선수 지식: Unit 5.2
핵심 개념
[이전 노드 주소 | 데이터 | 다음 노드 주소]자기 점검
선수 지식: Unit 5.2, Unit 5.3
핵심 질문:
"ArrayList도 LinkedList도 결국 O(n)인데, 왜 LinkedList가 삽입/삭제에 유리하다고 하는가?"
답: 비용의 종류가 다르다.
| 작업 | ArrayList | LinkedList |
|---|---|---|
| 위치 찾기 | O(1) (인덱스 직접 접근) | O(n) (순차 탐색) |
| 실제 삽입/삭제 | O(n) 메모리 복사 | O(1) 참조 변경 |
메모리 복사는 데이터 크기에 따라 비용이 더 크게 증가한다. 데이터가 많을수록 ArrayList의 복사 비용이 폭증.
검증 코드 (직접 돌려보면서 이해)
int[] arr = new int[5];
arr[0]=0; arr[1]=1; arr[2]=2; arr[3]=3;
// 인덱스 1에 99를 삽입하려면?
// arr[4]=arr[3], arr[3]=arr[2], arr[2]=arr[1], arr[1]=99
// → 데이터를 일일이 복사해서 밀어낸다
자기 점검
목표: 컴파일 타임 정보로 다 풀리지 않는 문제 두 가지 — 런타임에 클래스 정보 다루기, 컬렉션 통합 순회 — 의 해결책을 본다.
선수 지식: Phase 1 전체
핵심 개념
Object 를 상속 → metadata를 동반Class<?> API로 접근 가능자기 점검
obj.getClass() 가 반환하는 것은?Member.class 와 member.getClass() 의 차이는?선수 지식: Unit 6.1
핵심 개념
예시 (개념)
Class<?> clazz = Class.forName("org.example.Member");
Object obj = clazz.getDeclaredConstructor().newInstance();
Method m = clazz.getMethod("hap", int.class, int.class);
m.invoke(obj, 1, 2);
자기 점검
선수 지식: 1주차 Phase 6
핵심 문제:
Iterator가 없던 시절, 컬렉션마다 순회 방식이 달랐다.
// ArrayList: 인덱스 순회
for (int i = 0; i < list.size(); i++) { list.get(i); }
// HashSet: 인덱스가 없어서 다른 방식 필요
// LinkedList: 또 다른 방식
문제점:
자기 점검
선수 지식: Unit 6.3
핵심 개념
Collection 이 iterator() 메서드 제공Iterator 인터페이스: hasNext(), next(), remove()Collection<String> c = new ArrayList<>(); // 또는 HashSet, LinkedList
Iterator<String> it = c.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
for-each 문은 내부적으로 Iterator를 사용자기 점검
for-each 와 Iterator의 관계는?목표: 1주차의 NIO에서 등장했던 Buffer를 좀 더 일반적인 개념으로 이해한다.
선수 지식: 1주차 Phase 7
핵심 개념
ByteBufferBufferedReader / BufferedWriter (I/O 성능)자기 점검
원본 자료: JVM 밑바닥까지 파헤치기, p.69
main() 이 Static Zone에 있어야 하는 이유는?new Model2() 한 줄이 JVM에서 하는 4가지를?#7 같은 표기는 무엇을 의미하는가?invokespecial 과 invokevirtual 의 차이는?for-each 와 Iterator의 관계는?반드시 깊이 파기 (면접 단골 + 실무 직결):
기본 이해로 충분:
[ ] Phase 1 — 자바 변수 ↔ 메모리 매핑 (Unit 1.1~1.6)
[ ] Phase 2 — JVM 메서드 실행 메커니즘 (Unit 2.1~2.4)
[ ] Phase 3 — 바이트코드와 상수 풀 (Unit 3.1~3.4) ★ 정점
[ ] Phase 4 — G1 GC 심화 (Unit 4.1~4.5)
[ ] Phase 5 — 컬렉션 내부 구조 (Unit 5.1~5.4)
[ ] Phase 6 — Reflection & Iterator (Unit 6.1~6.4)
[ ] Phase 7 — Buffer (Unit 7.1)
[ ] 종합 자기 점검 25문항 통과
javap -c MyClass.class: 바이트코드 읽기javap -v MyClass.class: 상수 풀까지 보기java -XX:+PrintGCDetails: GC 로그 확인java -XX:+UseG1GC: G1 GC 강제 활성화| Phase | ILIC 실무 연결 |
|---|---|
| 1~2 (JVM 메모리/실행) | OOM 분석, heap dump 읽기, 스레드 덤프 |
| 3 (바이트코드/상수 풀) | Spring AOP 동작 이해, 빌드 산출물 분석 |
| 4 (G1 GC) | 운영 서버 GC 튜닝, GC 로그 분석 |
| 5 (컬렉션 내부) | DTO/Entity 컬렉션 매핑 시 자료구조 선택 |
| 6 (Reflection) | Spring DI, JPA Entity, Jackson DTO 매핑 이해 |
| 6 (Iterator) | Stream API의 기반 (3주차로 확장) |
| 7 (Buffer) | 파일 업로드 처리, NIO 활용 |