Run Java

Su Suriya Ravichandran Updated 14 Nov 2026
8 min read ·Lesson 38 of 133

The java command starts a Java Virtual Machine and runs a program in it. It can launch a compiled class, a packaged JAR file, or a source file directly. This lesson covers each form, how the JVM finds the classes it needs, how to pass arguments and settings into a program, and how a program reports success or failure when it ends.

Running a Compiled Class

javac Hello.java
java Hello

Note the difference between the two commands:

CommandTakesExample
javacA file name, with .javajavac Hello.java
javaA class name, without .classjava Hello

Writing java Hello.class fails:

Error: Could not find or load main class Hello.class
Caused by: java.lang.ClassNotFoundException: Hello.class

The JVM interprets Hello.class as a class named class in a package named Hello. Give the class name only.

The main method requirement

The class must have a valid entry point. The standard form is:

public static void main(String[] args)

If it is missing or has the wrong signature:

Error: Main method not found in class Hello, please define the main method as:
   public static void main(String[] args)
...

Since Java 25, the launcher also accepts simpler entry points, such as an instance void main() with no parameters, used mainly in compact source files for beginners and scripts. The standard form above works on every Java version.

How the JVM Finds Classes: the Classpath

The JVM loads classes from the locations on the classpath, a list of directories and JAR files. By default the classpath is the current directory (.). Set it explicitly with -cp (or the long form --class-path):

java -cp out Hello

For a class in a package, give the fully qualified name, and point the classpath at the directory that contains the package's top-level folder:

out/
└── com/example/app/Main.class
java -cp out com.example.app.Main          # correct
java -cp out/com/example/app Main          # wrong: Main is not in the unnamed package

The JVM converts com.example.app.Main into the path com/example/app/Main.class and searches for it under each classpath entry. The second form finds the file but rejects it, because the class declares package com.example.app and is being loaded as if it had none.

Multiple entries are separated by : on macOS/Linux and ; on Windows:

java -cp "out:lib/*" com.example.app.Main           # macOS / Linux
java -cp "out;lib\*" com.example.app.Main           # Windows

lib/* includes every JAR in the lib directory. Quote it so the shell does not expand the wildcard.

"Could not find or load main class"

This is the most common launch error. Check, in order:

  1. Is the name correct, including capitalization and the full package?
  2. Is the classpath pointing at the directory above the package folders?
  3. Was the code compiled successfully, and is the .class file where you expect it?
  4. If -cp is set, does it include . or out (wherever your classes are)? Setting -cp replaces the default current directory.

Similarly, NoClassDefFoundError at runtime, rather than at launch, means a class your program uses (often from a library JAR) is not on the classpath.

Passing Command-Line Arguments

Everything after the class name is passed to the program in the args array:

public class Sum {
    public static void main(String[] args) {
        int total = 0;
        for (String a : args) {
            total += Integer.parseInt(a);
        }
        System.out.println("Arguments: " + args.length + ", total: " + total);
    }
}
java Sum 10 20 30
Arguments: 3, total: 60

Arguments are always strings, split on spaces by the shell. Quote an argument that contains spaces:

java Greet "Ada Lovelace"       # args[0] is "Ada Lovelace"
java Greet Ada Lovelace         # args[0] is "Ada", args[1] is "Lovelace"

Options placed before the class name go to the JVM; arguments placed after it go to the program:

java -Xmx512m -Dmode=test Sum 1 2 3
#    └── JVM options ──┘ └class┘ └─ program arguments ─┘

Running a JAR File

Applications are usually distributed as JAR files. If the JAR's manifest names a main class, run it with -jar:

java -jar inventory.jar
java -jar inventory.jar --port 8080      # with program arguments

The manifest (META-INF/MANIFEST.MF inside the JAR) contains a line like Main-Class: com.example.app.Main. If it is missing:

no main manifest attribute, in inventory.jar

In that case, name the class explicitly:

java -cp inventory.jar com.example.app.Main

With -jar, the -cp option and the CLASSPATH environment variable are ignored. Dependencies must be listed in the manifest's Class-Path attribute or bundled into the JAR itself (a "fat" or "uber" JAR, which build tools can produce). JAR files have their own lesson.

Running Source Files Directly

Since Java 11, java can run a source file without a separate compile step:

java Hello.java

The launcher compiles the file in memory, then runs the first top-level class it declares. No .class file is written. This is ideal for small programs, quick experiments, and scripts.

java Sum.java 4 5 6
# Arguments: 3, total: 15

Since Java 22, the source launcher can also run a program spread across several source files: when the main file refers to another class, the launcher finds and compiles that class's source file from the same directory tree. Libraries can be added with --class-path.

Shebang scripts (macOS / Linux)

A source file can be made directly executable. The file must not end in .java:

#!/usr/bin/env -S java --source 21
public class Backup {
    public static void main(String[] args) {
        System.out.println("Backing up " + (args.length > 0 ? args[0] : "."));
    }
}
chmod +x backup
./backup /home/ada/projects

The first line tells the operating system to run the file with java --source 21. This turns small Java programs into command-line tools without a build step.

JVM Options

Options before the class or -jar configure the JVM itself:

OptionPurpose
-cp, --class-pathWhere to find classes
-Dname=valueSet a system property, read with System.getProperty("name")
-Xmx2g, -Xms512mMaximum and initial heap size
-Xss1mThread stack size
-eaEnable assert statements (disabled by default)
-verbose:classLog every class as it is loaded
-Xlog:gcLog garbage collection
-version, --versionPrint the Java version (to stderr and stdout respectively) and exit
-XshowSettings:allPrint JVM settings, system properties, and locale information

Example: run with a property and assertions enabled:

public class Config {
    public static void main(String[] args) {
        String env = System.getProperty("app.env", "development");
        int workers = Integer.getInteger("app.workers", 2);
        assert workers > 0 : "workers must be positive";
        System.out.println("Environment: " + env + ", workers: " + workers);
    }
}
java -ea -Dapp.env=production -Dapp.workers=8 Config
Environment: production, workers: 8

System.getProperty takes a default used when the property is not set. Integer.getInteger reads a system property and parses it as an integer. Without -ea, the assert line is skipped entirely, which is why assertions are used for development checks rather than for validating real input.

JDK_JAVA_OPTIONS

Options can also come from the JDK_JAVA_OPTIONS environment variable, which the java launcher prepends to its command line:

export JDK_JAVA_OPTIONS="-Xmx1g -Duser.timezone=UTC"
java -jar app.jar

This is useful in containers and CI environments where the launch command is fixed but settings need to vary.

Exit Codes

When a program finishes, the JVM returns an exit code to the operating system. 0 means success; any other value indicates failure. Scripts and CI systems rely on it to decide whether a step succeeded.

How the program endsExit code
main returns normally (and no non-daemon threads remain)0
System.exit(n)n
An uncaught exception ends the main thread1
The launcher fails (class not found, bad option)1
public class Validate {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.err.println("Usage: java Validate <file>");
            System.exit(2);
        }
        System.out.println("Validating " + args[0]);
    }
}
java Validate
echo $?            # macOS/Linux: prints 2
                   # Windows: echo %ERRORLEVEL%  (cmd) or $LASTEXITCODE (PowerShell)

Use System.err for error messages so they stay separate from normal output, and a nonzero exit code so callers can detect failure. Avoid System.exit inside library code or web applications, where it would shut down the entire JVM, including everything else running in it.

Practical Example: A Small Command-Line Tool

// WordStats.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class WordStats {
    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage: java WordStats <file>");
            System.exit(2);
        }
        Path file = Path.of(args[0]);
        try {
            String text = Files.readString(file);
            long lines = text.lines().count();
            long words = text.isBlank() ? 0 : text.strip().split("\\s+").length;
            boolean verbose = Boolean.getBoolean("verbose");

            System.out.println(lines + " lines, " + words + " words");
            if (verbose) {
                System.out.println("File: " + file.toAbsolutePath());
                System.out.println("Size: " + Files.size(file) + " bytes");
            }
        } catch (IOException e) {
            System.err.println("Cannot read " + file + ": " + e.getMessage());
            System.exit(1);
        }
    }
}
java WordStats.java notes.txt
java -Dverbose=true WordStats.java notes.txt
java WordStats.java missing.txt; echo "exit code: $?"

Example output:

12 lines, 148 words

12 lines, 148 words
File: /home/ada/notes.txt
Size: 861 bytes

Cannot read missing.txt: missing.txt
exit code: 1

The program takes the file name as a command-line argument, reads an optional verbose flag as a system property (Boolean.getBoolean returns true only when the property is set to "true"), writes errors to standard error, and reports success or failure through its exit code. Run as a source file, it needs no build step at all, yet it behaves like any other command-line tool and can be used in shell scripts and automated pipelines.

0 Comments

Reviewed before they appear

No comments yet.

Java
Java Introduction Java Features Java Syntax Java Comments Java Statements Java Output Java Variables Java Data Types Java Type Casting Java Operators Java Strings Java Numbers Java Math Java Booleans Java User Input Java Conditions Java If Else Java Switch Java While Loop Java For Loop Java Break Java Continue Java Arrays Java Methods Java Parameters Java Return Values Java Scope Java Recursion Install Java Install JDK Java IDEs Java JDK Java JRE Java JVM Java Compiler Java File Compile Java Run Java JShell Basics Java Packages Java OOP Java Classes Java Objects Class Methods Constructors Constructor Overload this Keyword static Keyword final Keyword Encapsulation Inheritance Polymorphism Abstraction Access Modifiers super Keyword Method Overload Method Override Instanceof Operator Nested Classes Inner Classes Anonymous Classes Enums Records Array Basics Array Length Loop Arrays Multidimensional Arrays Array Copy Array Sorting Array Search ArrayList LinkedList HashSet TreeSet HashMap TreeMap Queue Interface Deque Interface Stack Class Iterator List Interface Set Interface Map Interface Collections Class Comparable Comparator Generics Basics Generic Classes Generic Methods Wildcards String Basics String Length String Methods String Concatenation String Compare String Search String Replace String Split String Format StringBuilder StringBuffer Text Blocks Regular Expressions Number Types Integer Class Float Class Double Class BigInteger BigDecimal Math Class Random Numbers Number Format Date Basics LocalDate LocalTime LocalDateTime ZonedDateTime Date Formatting Date Parsing Period Class Duration Class Java Instant Class Java Exception Basics Java try...catch Java Multiple Catch Blocks Java finally Block Java throw Keyword Java throws Keyword Java Checked Exceptions Java Unchecked Exceptions Java Custom Exceptions Java try-with-resources Java Exception Chaining
Ask about this post
AI Ask about this post

Ask questions about Run Java and get answers drawn from it.

Signed-in readers only.