JB Header

Compiling and Running Java Programs with javac and java

Introduction Every Java program goes through two steps before it produces any output - it is compiled by javac, and then run by java. This tutorial explains compiling and running Java programs with the javac and java commands. We will start with the basic compile-and-run cycle. We will then compile a program made of several classes, keep the compiled classes in a separate folder, and tell java where to find them with the classpath. Next we will run source files directly without compiling them first, and package a program into a runnable JAR file. Lastly, we will look at the errors you will see when something goes wrong.

(Note - If you have not written a Java program yet, start with the Hello World program explained line by lineClick to read tutorial: Java Hello World Program Explained Line by Line.) The compile and run cycle Let us take a small program which greets the user.
A simple Java program
//Hello.java
public class Hello {
  public static void main(String[] args) {
    System.out.println("Hello from Java!");
  }
}
The two steps are -
  1. Compile: javac Hello.java reads the source file, checks it for errors, and writes the bytecode to Hello.class. Note that javac takes a file name, including .java.
  2. Run: java Hello starts a Java Virtual Machine, loads the class Hello from Hello.class, and calls its main() method. Note that java takes a class name, without .class.
javac Hello.java
java Hello
 OUTPUT of the above commands
Hello from Java!
If the compilation succeeds, javac prints nothing at all. You only need to compile again after you change the source code. Compiling a program with several classes Real programs are made of many classes, usually one per file. Here the App class uses a Greeter class from another file.
Greeter.java - a class used by the program
//Greeter.java
public class Greeter {
  public String greet(String name) {
    return "Hello, " + name + "!";
  }
}
App.java - the class with the main() method
//App.java
public class App {
  public static void main(String[] args) {
    Greeter greeter = new Greeter();
    System.out.println(greeter.greet("Harry"));
  }
}
You can list all the files to compile, or use a wildcard. javac also compiles any class that the listed files use, if it finds its source file in the same folder. You then run the class which has the main() method -
javac App.java Greeter.java
java App
 OUTPUT of the above commands
Hello, Harry!
Keeping compiled classes separate with -d By default javac writes each .class file next to its source file. The -d option writes them to another folder instead, keeping your source folder clean. The folder is created if it does not exist.
javac -d out App.java Greeter.java
dir /b out
(On macOS and Linux, use ls out instead of dir /b out.)  OUTPUT - the class files in the out folder
App.class
Greeter.class
Telling java where the classes are - the classpath The JVM looks for classes on the classpath - a list of folders and JAR files. By default, the classpath is the current folder, which is why java Hello found Hello.class earlier. Now that the classes are in out, we pass that folder with the -cp option (short for -classpath) -
java -cp out App
 OUTPUT of the above command
Hello, Harry!
To put several folders or JAR files on the classpath, separate them with ; on Windows and : on macOS and Linux - for example java -cp out;lib\helper.jar App on Windows.

Note - When classes belong to a package, such as com.javabrahman.App, -d creates the matching folders (out/com/javabrahman/), and you run the class by its full name: java -cp out com.javabrahman.App. Packages are covered later in this series. Running a source file directly - no javac needed Since Java 11, the java command can run a .java source file directly. It compiles the file in memory and runs it, without creating any .class file. This is called source-file mode, and it is very handy for small programs and quick experiments.
java Hello.java
 OUTPUT of the above command
Hello from Java!
Since Java 22, source-file mode also works for programs made of several files - the launcher finds and compiles the other classes in the same folder when they are needed -
java App.java
 OUTPUT of the above command
Hello, Harry!
Note - Source-file mode recompiles the program every time it runs. For bigger programs, compile once with javac - or let an IDE or build tool do it for you.
Packaging the program into a runnable JAR A JAR (Java ARchive) file bundles all of a program's classes into one file, which is how Java programs are usually shared. The JDK's jar tool creates it; --main-class records which class to run, and -C out . adds everything in the out folder. A runnable JAR is then started with java -jar -
jar --create --file app.jar --main-class App -C out .
java -jar app.jar
 OUTPUT of the above commands
Hello, Harry!
Common errors when running programs 1. Adding .class to the class name - java treats App.class as a class named class in a package named App, which does not exist -  OUTPUT of java -cp out App.class
Error: Could not find or load main class App.class
Caused by: java.lang.ClassNotFoundException: App.class
2. The class is not on the classpath - here the classes are in out, but -cp points elsewhere -  OUTPUT of java -cp classes-missing App
Error: Could not find or load main class App
Caused by: java.lang.ClassNotFoundException: App
3. Running a class which has no main() method -  OUTPUT of java -cp out Greeter
Error: Main method not found in class Greeter, please define the main method as:
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
Explanation of the errors
  • Could not find or load main class almost always means either a typo in the class name, a .class or .java ending added by mistake, or a wrong classpath. Check the class name (it is case-sensitive) and the folder passed to -cp.
  • Main method not found means the class was found, but it has no public static void main(String[] args) method. Run the class that has main() - here, App.
Summary In this tutorial we first went through the compile-and-run cycle - javac takes a file name and produces .class files, and java takes a class name and runs it. We then compiled a program made of two classes, kept the compiled classes in a separate folder with -d, and ran them with -cp. Next we ran source files directly in source-file mode, for single files and, since Java 22, for programs with several files. We then packaged the program into a runnable JAR. Lastly, we looked at the most common errors when running programs and what causes them. In the next tutorial, we will see what happens inside the JVMClick to read tutorial: How Java Code Runs: Bytecode, Class Loader and JIT when it runs a program.