
안녕하세요! 백엔드 개발자 취준생^^ 현영입니다.
오늘부터 JVM.js라는 프로젝트를 시작하려고 해요.
JVM.js는 브라우저에서 동작하는 Mini JVM 구현체로, Java 바이트코드를 파싱하고 실행하며, 그 과정을 실시간으로 시각화하는 교육용 도구입니다.
1년 넘게 Java/Spring으로 백엔드 개발을 해오면서, 항상 "JVM이 내부적으로 어떻게 동작하는지" 궁금했습니다.
JVM 스터디를 하면서 이론은 배웠지만, 직접 만들어보면 훨씬 더 깊이 이해할 수 있지 않을까? 하는 생각이 들었어요.
게다가 이걸 웹에서 시각화하면:
그래서 시작하게 되었습니다.
// 이 정도 코드가 실행되는 것이 목표!
// 굉장히 간단하죠?
public class FizzBuzz {
public static void main(String[] args) {
for (int i = 1; i <= 15; i++) {
if (i % 15 == 0) {
System.out.println("FizzBuzz");
} else if (i % 3 == 0) {
System.out.println("Fizz");
} else if (i % 5 == 0) {
System.out.println("Buzz");
} else {
System.out.println(i);
}
}
}
}
✅ Java .class 파일 파싱
✅ 바이트코드 명령어 실행 (30개 이상)
실시간 시각화 (Stack, Local Variables, PC) <- 이것도 할 수 있음 좋겠어요
✅ Step-by-step 실행
✅ 산술연산, 조건문, 반복문, 메서드 호출 지원
(가능할지 모르겠지만) GC 구현
┌──────────────────────┬──────────────────────┐
│ 📝 Bytecode │ 🎯 Runtime │
├──────────────────────┼──────────────────────┤
│ 0: iconst_1 ← │ Operand Stack │
│ 1: istore_1 │ ┌────────────────┐ │
│ 2: iconst_1 │ │ 1 │ │
│ 3: istore_2 │ └────────────────┘ │
│ 4: iload_2 │ │
│ 5: bipush 15 │ Local Variables │
│ 6: if_icmpgt 50 │ [1]: 1 │
│ ... │ [2]: 1 │
│ │ │
│ │ PC: 0 │
├──────────────────────┴──────────────────────┤
│ ⏯️ [Step] [Run] [Reset] │
├──────────────────────────────────────────────┤
│ 📤 Output │
│ 1 │
│ 2 │
│ Fizz │
└──────────────────────────────────────────────┘
총 4주, 매일 3시간씩 투자할 계획입니다.
목표: .class 파일을 읽어서 바이트코드 추출하기
세부 일정:
Day 1 : 프로젝트 셋업 + JVM 스펙 조사
Day 2 : Magic Number & Version 파싱
Day 3: Constant Pool 파싱 (1)
Day 4 : Constant Pool 파싱 (2)
Day 5 : Method 영역 파싱
Day 6-7: 파서 완성 + 리팩토링
산출물:
.class 파일 파싱 성공목표: 간단한 Java 코드 실행하기
핵심 구현:
구현할 명령어:
- 상수: iconst_*, bipush
- 로드/스토어: iload_*, istore_*
- 산술: iadd, isub, imul, idiv, irem
- 비교/분기: if_icmp*, goto
- 증감: iinc
테스트 목표:
// 이런 코드가 실행되어야 함
public class Test {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum = sum + i;
}
}
}
산출물:
목표: 메서드 호출 지원 + UI 구현
핵심 구현:
테스트 목표:
public class Test {
public static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int result = add(5, 10);
System.out.println(result);
}
}
산출물:
목표: 프로젝트 완성 + 배포
작업 내용:
최종 산출물:
어려운 점:
해결 방안:
어려운 점:
해결 방안:
어려운 점:
해결 방안:
GitHub 레포 생성
jvm.js프로젝트 구조 잡기
jvm.js/
├── src/
│ ├── parser/
│ │ ├── ClassFileParser.js
│ │ ├── ConstantPoolParser.js
│ │ └── MethodParser.js
│ ├── runtime/
│ │ ├── StackFrame.js
│ │ ├── ThreadStack.js
│ │ └── RuntimeDataArea.js
│ ├── executor/
│ │ ├── ExecutionEngine.js
│ │ └── Instructions.js
│ └── visualizer/
│ ├── Visualizer.js
│ └── Disassembler.js
├── test/
│ └── fixtures/
│ ├── Simple.java
│ └── Simple.class
├── index.html
├── style.css
└── README.md
// test/fixtures/Simple.java
public class Simple {
public static void main(String[] args) {
int x = 5;
}
}
# 컴파일
javac test/fixtures/Simple.java
# hex dump로 구조 확인
xxd test/fixtures/Simple.class
# javap로 바이트코드 확인
javap -c -v test/fixtures/Simple.class
4주라는 시간이 짧다면 짧고 길다면 긴 시간입니다. 그 전에 취직에 성공해서 이 프로젝트를 때려칠 수 있다면 너무 좋겠어요.....
무엇보다 이 과정에서 JVM에 대한 이해가 훨씬 깊어질 것이고,
그 배움을 블로그를 통해 다른 분들과도 나눌 수 있다면 더욱 의미있는 프로젝트가 될 것 같습니다.
함께 지켜봐주시고, 응원해주세요! 🔥
다음 글 예고: Class 파일 파싱하기 - CAFEBABE의 비밀
#JVM #JavaScript #브라우저JVM #백엔드개발 #포트폴리오 #4주프로젝트 #JVM내부구조 #바이트코드
우와~~ 정말 좋은 아이디어 같아요!! 나중에 코헤 님 따라 만들어 보고 싶어요 🔥🔥 다음 글도 기대됩니다