
javac 명령어로 java 파일 -> class 파일 작업하는 것을 컴파일이라 한다.
이 컴파일은 위와 같은 단계로 이뤄진다.
실제 코드레벨로는 com.sun.tools.javac.main.JavaCompiler
어휘 분석 : int a = b + 2 와 같은 코드를 int, a, = , b, +, 2 와 같이 토큰으로 분리한다.
구문 분석 : 토큰으로 추상 구문 트리 만든다. 추상 구문 트리는 코드를 기계가 더 이해하기 쉬운 데이터 구조이며, 이후 컴파일 레벨의 작업은 모두 추상 구문 트리를 대상으로 이뤄진다.
어휘 및 구문 분석에는 구조적으로 올바른지 체크하고 문제가 있다면 예외를 발생한다.
intellij 의 PsiViewer 플러그인을 사용하면 추상 구문 트리를 시각적으로 볼 수 있다.

심벌 테이블 : 심벌 주소와 심벌 정보의 집합
기본 생성자가 만들어지는 타이밍이기도 하다.
플러그인된 애너테이션 처리기의 처리를 진행한다.
애너테이션 처리기(processor) : 컴파일 타임에 애너테이션을 보고 바이트 코드를 생성하는 기술
대표적으로 애너테이션은 런타임에 처리되는 Spring AOP 를 생각할 수 있다.
애너테이션 처리기는 컴파일 타임에 애너테이션을 활용하는 방법이다.
이 단계에서 추상 구문 트리의 수정이 발생하면 구문 분석 및 심벌 테이블 채우기 단계를 다시 실행해야 한다.
이 단계의 추상 구문 트리는 구조적으로 올바른 상태이다.
의미 분석 단계에는 맥락상 논리적으로 올바른지 체크한다.
(구조적으로 이상하게 작성한게 아닌)보통의 컴파일 타임 에러는 이 단계에서 체크된다.
변수를 사용하기 앞서 선언이 되어 있는지
변수와 할당될 데이터의 타입이 일치하는지
상수 접기 최적화(1 + 2 -> 3 으로 컴파일)
프로그램이 맥락상 논리적으로 올바른가를 체크
클래스 로딩 시의 제어 흐름 분석 검증과 비슷하지만 범위가 다르다.
지역 변수의 final 로 예를 들어 보자.
필드의 final 은 필드 테이블에 플래그로 final 임이 저장된다. 따라서 런타임에 해당 필드가 변경되면 에러를 낼 수 있다.
반면에 지역 변수 테이블에 저장되는 지역 변수는 클래스 파일에는 단순한 심벌 참조만이 존재하므로 런타임에 지역 변수가 final 임을 알 수 없다.
즉, 지역 변수의 final 은컴파일 타임에만검사된다.
런타임에는 영향을 주지 않고 더 효율적인 코딩만을 위한 코드를 편의 문법이라 한다.
컴파일 타임의 이 단계에서는 해당 편의 문법을 제거한다.
편의 문법의 예는 다음과 같다.
지금까지의 정보로 바이트코드를 생성한다.
인스턴스 생성자 <init>(), <clinit>() 은 이 단계에서 추가된다.