for 문으로 1부터 5까지 더하면 15가 찍힌다. 그동안 JVM 메모리에서 바뀌는 곳은 어디일까?
public class Sum {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 5; i++) {
sum += i;
}
System.out.println(sum);
}
}
아래 재생기의 ▶를 누르면 한 스텝씩 진행된다. 금색 테두리가 지금 이야기하는 곳이고, 캡션이 무슨 일이 일어났는지 말해 준다. 굵게 밑줄 친 말은 누르면 뜻이 나온다. 빨간 딱지는 그때 벌어지는 일의 이름이고, 캡션 바로 위 회색 글자는 지금 스텝이 속한 묶음의 이름이다.
카드 아래 회색 줄은 그 일이 실제로 적혀 있는 소스의 파일 이름 : 줄 번호와 함수 이름이다. 글 안에 (:669)처럼 줄 번호만 적힌 것은 바로 앞에 적은 파일의 그 줄이라는 뜻이다. 캡션 한가운데 박힌 긴 영어 이름과 괄호 속 파일 · 줄 번호도 같다 — 건너뛰고 한글만 읽어도 뜻이 통하게 써 두었다.
장면 · 1부터 5까지 더하기0 / 24
아직 아무 명령도 실행하지 않았다. main 프레임이 방금 만들어졌고, 칸 0에는 args 배열을 가리키는 참조만 들어 있다. 인자 없이 실행해서 args는 길이 0인 배열(String[0])이다. 힙의 PrintStream은 4단계 9번에서 만들어 둔 System.out이다. 힙에는 이 장면에 관계된 객체만 그렸다 — 실제로는 JVM이 main 전에 만든 객체가 훨씬 많다.
키보드 · ← → 한 스텝 · Space 재생/멈춤 · Home 처음
반복하는 동안 바뀌는 것은 칸 1(sum)과 칸 2(i), 그리고 크기 2짜리 스택뿐이다. 반복 구간에는 객체를 만드는 명령(new, 6단계)이 없어서 힙은 그대로다. 힙에 새 객체가 생기는 것은 마지막 println에서인데, main이 아니라 불려 간 println 안에서 String을 만든다.
어떻게 확인했나
소스 어디를 보고 적었는지와 무엇을 돌려서 쟀는지를 남긴 자리다. 처음 읽을 때는 건너뛰어도 된다.
칸의 값은 jdb로 반복마다 멈춰 읽은 실제 값이다 (JDK 21.0.10).
명령과 칸 크기는 javap -c -l 출력이다 — stack=2, locals=3.
피연산자 스택의 값은 디버거로 볼 수 없어서, 명령의 뜻(JVM 명세)대로 따라가 그렸다.
이 main은 끝까지 인터프리터로 돌았다. 기계어로 번역한 메서드를 찍어 주는 옵션(-XX:+PrintCompilation)으로 돌렸는데 Sum이 한 줄도 나오지 않았다.