Skip to content
Part IA Michaelmas Term

Compiling and Running Java Programs

The Core Commands

Three commands form the basic Java workflow:

CommandPurpose
javacCompile .java source files to .class bytecode files
javaLaunch the JVM and execute the bytecode in a .class file
jshellInteractive REPL for trying out Java code snippets

javac — The Java Compiler

The javac command reads .java source files and produces .class bytecode files. The filename of a public class must match the filename: HelloWorld.java must define public class HelloWorld.

javac HelloWorld.java

This produces HelloWorld.class in the current directory. If the source file contains multiple classes (at most one public), javac produces one .class file per class.

Useful Flags

FlagPurpose
-d <dir>Specify output directory for .class files (default: same directory as source)
-cp <path> or -classpath <path>Specify where to find other .class files or JARs needed during compilation
-sourcepath <path>Where to find .java source files (default: current directory)
-encoding <encoding>Specify source file encoding (e.g. UTF-8)

If your program depends on external libraries, you must tell javac where to find them. Assuming a library JAR at lib/utils.jar:

javac -cp lib/utils.jar:. src/MyProgram.java -d out/

The :. (or ;. on Windows) includes the current directory in the classpath so that previously compiled classes can be found.

java — The JVM Launcher

The java command starts the JVM and runs the main method of the specified class. Note: you provide the class name, not the filename — no .class extension.

java HelloWorld

The JVM loads the class, verifies the bytecode, and executes public static void main(String[] args).

Useful Flags

FlagPurpose
-cp <path> or -classpath <path>Where to find .class files and JARs at runtime
-ea or -enableassertionsEnable assertions (off by default)
-Xmx<size>Set maximum heap size (e.g. -Xmx512m for 512 MB)
-versionPrint JVM version and exit

Classpath at runtime works the same as at compile time:

java -cp lib/utils.jar:out/ MyProgram

jshell — The Interactive REPL

jshell, introduced in Java 9, provides a Read-Eval-Print Loop for interactive experimentation. It lets you write Java statements, expressions, and declarations without a full compile-build-run cycle. This is useful for exploring APIs, testing small code snippets, and learning the language.

jshell> int x = 42;
x ==> 42

jshell> x * 2
$2 ==> 84

jshell> String s = "Hello, " + x;
s ==> "Hello, 42"

jshell supports tab completion, forward references, and declaration redefinition. It uses a slightly relaxed syntax — semicolons are optional for top-level expressions. To exit, type /exit.

The Build-Run Cycle

A typical development workflow:

javac -d out/ src/HelloWorld.java
java -cp out/ HelloWorld

For a multi-file project:

javac -d out/ src/*.java
java -cp out/ MainClass

Or, if you are avoiding explicit compilation during experimentation:

java src/HelloWorld.java

Since Java 11, the java command can directly run a single source file — it compiles the file in memory and executes it. This is convenient for small scripts but does not produce persistent .class files.

Comparison with Python

Python does something similar under the hood:

JavaPython (CPython)
Source.java.py
Compiled to.class bytecode.pyc bytecode (cached in __pycache__/)
Execution engineJVMCPython VM (interpreter)
Compile stepExplicit (javac)Implicit (automatic on import or first run)

Both languages compile to a platform-independent bytecode and then execute it on a virtual machine. The key difference is that Python hides the compilation step — you rarely see .pyc files unless you look for them — while Java makes it an explicit part of the workflow.

Common Pitfalls

  • Class name mismatch: public class HelloWorld must be in a file called HelloWorld.java, and the java command expects the class name, not HelloWorld.class or HelloWorld.java
  • Classpath issues: if your classes are in out/, you must include out/ on the classpath when running
  • Forgetting to recompile: after editing a .java file, you must run javac again before running java — the JVM sees the .class file, not the source
  • Case sensitivity: helloworld and HelloWorld are different identifiers on all platforms (unlike Windows filenames)