javac
Compile Java source code to bytecode
TLDR
Compile a .java file
Compile several .java files
Compile all .java files in current directory
Compile a .java file and place the resulting class file in a specific directory
SYNOPSIS
javac [options] sourcefiles | @files
PARAMETERS
-d directory
Specifies the root directory where the compiler should place the generated .class files.
-cp path, --class-path path
Specifies the search path for user class files and annotation processors. Directory entries or JAR file entries are separated by platform-specific path separators (e.g., : on Linux, ; on Windows).
-source release
Provides source compatibility with the specified Java release. For example, -source 8 compiles code compatible with Java 8.
-target release
Generates class files that are compatible with the specified JVM version. For example, -target 11 ensures the bytecode can run on a Java 11 or newer JVM.
-encoding encoding
Specifies the character encoding used by the source files, such as UTF-8 or ISO-8859-1.
-verbose
Outputs messages about what the compiler is doing, including class loading and source file compilation.
-g
Generates all debugging information, including local variables, line numbers, and source file information. This is useful for debugging with tools like jdb.
-Xlint[:option]
Enables recommended warnings. Common options include all, unchecked, deprecation, rawtypes.
-version
Prints the compiler version string and exits.
--help, -h
Prints a synopsis of standard options and exits.
DESCRIPTION
The javac command is the primary tool of the Java Development Kit (JDK) used for compiling Java source code into bytecode. It takes one or more .java source files as input and produces .class files, which contain platform-independent bytecode that can be executed by the Java Virtual Machine (JVM).
javac performs rigorous syntax checking, type checking, and various optimizations during the compilation process. It resolves dependencies between classes, interfaces, and other types, ensuring that all required components are available and correctly referenced. This essential compilation step transforms human-readable Java code into the low-level instructions understood by the JVM, making it a foundational component for developing and deploying any Java application.
CAVEATS
javac requires the Java Development Kit (JDK) to be installed, not just the Java Runtime Environment (JRE).
Managing large projects directly with javac can be cumbersome; build tools like Maven or Gradle are typically used for dependency management and build automation.
Careful attention is required for classpath management (-cp) to ensure all necessary libraries are found during compilation.
Mismatch between -source and -target options can lead to unexpected runtime issues if the target JVM is older than the source version.
COMPILATION PROCESS OVERVIEW
When you run javac, it goes through several phases:
1) Parsing: The source code is broken down into a syntax tree.
2) Semantic Analysis: The compiler checks for type compatibility, resolves names, and builds a symbol table.
3) Code Generation: The syntax tree is translated into JVM bytecode instructions, which are then written to .class files. Error messages are produced at any stage if issues are found.
MODULE PATH (JAVA 9+)
For projects utilizing Java's module system (introduced in Java 9), the -p or --module-path option is used instead of or in addition to -cp. It specifies the search path for application modules. This allows the compiler to resolve module dependencies and ensures proper encapsulation and strong type checking across module boundaries.
HISTORY
javac was first introduced by Sun Microsystems (now Oracle) as a core component of the Java Development Kit (JDK) with the initial release of Java 1.0 in 1996. Its development has closely paralleled the evolution of the Java language itself, with new versions of javac being released to support new language features (e.g., generics in Java 5, lambdas in Java 8, modules in Java 9). It has remained a fundamental tool for Java developers, providing the bridge between human-readable source code and executable bytecode for the Java Virtual Machine.