01
Build Tools
The build tool's life cycle, target and task model; which class path a dependency scope makes a type visible on, that a transitive dependency can be required at run time without appearing at compile time, and what determines resolution when two candidates for the same name turn up; the compile-time counterpart of module boundaries; how the executable output that packaging produces carries the runtime path.
- 01 Build Tool Model The phase sequence a build tool derives from a declaration is fixed and unaffected by the declaration's writing order: three declared items yield four phases, and both a forward and a reversed writing of the same declaration derive the same four phases. Two class paths coming out of the same declaration — one for compiling, one for running — are separated by an annotation type kept at the source level: it never appears in the class file's constant pool, and it is never required on the runtime class path either.
- 02 Dependency Management The same source is first compiled against a compile class path and then run against a separate runtime class path: of six types, 1 turns out required only at compile time, 3 only at run time, 2 at both. Of four defects, 1 is a compile error, 1 is a runtime error, and 2 silently produce a wrong result without saying anything — one a choice tied to the order of two implementations of the same interface, the other the price of changing a constant without recompiling the caller.
- 03 Multi-Module Projects Of three boundary setups, one is caught at compile time, one at run time, one crosses the boundary silently without ever being caught. The limiting measurement shows why: Public and Internal are compiled into the same directory, and what actually builds the boundary is not the directory but a loader's allow list — of two class files in the same directory, one can be loaded while the other is rejected with a ClassNotFoundException.
- 04 Packaging and Executable Output The same archiving call produces both a self-sufficient archive and an archive dependent on an outside class: the first is sufficient on its own on the runtime class path, the second drops with a NoClassDefFoundError on its own and only runs once the missing directory is added. The entry point, too, lives not in the source but in the archive's own manifest: an undeclared archive produced from the same classes has no such information at all.