This 512-page book describes the phases of a compiler from lexical analysis through code generation using Java classes as examples. It covers parsing, abstract syntax, semantics, intermediate representations, instruction selection, dataflow analysis, register allocation, and runtime systems. The second edition has been expanded to include more discussion of Java concepts like visitor patterns. It includes a redesigned compiler project in Java that allows students to build a complete compiler in one semester.