The Java classpath is the list of folders and JAR files in which the JVM and the javac compiler look for classes and resources that are not part of the JDK. We set it with the -cp option (also written -classpath or –class-path) or with the CLASSPATH environment variable, and without either one the classpath is the current directory.
We need the classpath whenever our code uses a library outside the JDK, such as a JDBC driver or a JSON parser, and whenever the compiled classes are in another folder than the one we start java from. Build tools such as Maven and Gradle and IDEs build the classpath for us, but it is still the classpath that the JVM reads.
The following example compiles and runs a small recipe app that needs the library lib/units.jar. The commands are for Windows, where entries are separated by a semicolon. Linux and macOS use a colon instead.
javac -cp lib\units.jar -d classes src\com\howtodoinjava\recipes\RecipeApp.java
java -cp "classes;lib\*" com.howtodoinjava.recipes.RecipeApp
Flour: 300 g
Inside the running app, the system property java.class.path shows the classpath the JVM uses, with the wildcard already replaced by the JAR files it found.
String classpath = System.getProperty("java.class.path"); // "classes:lib/units.jar" on Linux for -cp "classes:lib/*"
String separator = File.pathSeparator; // ";" on Windows, ":" on Linux and macOS
Notice that javac needs only the library, whereas java needs the library and the folder with our compiled classes. We cover the search rules, the -cp option and the environment variable, executable JAR files, common errors, and how the classpath differs from the sourcepath, the module path and an IDE build path.
1. How the JVM Searches the Classpath
A classpath entry is either a folder, a JAR file or a folder with a wildcard. When the app class loader needs a class such as com.howtodoinjava.units.Units, it converts the package name into the relative path com/howtodoinjava/units/Units.class and looks for that path in each entry, in the order of the list.
- A folder entry is the root of the package tree, so classes holds classes/com/howtodoinjava/recipes/RecipeApp.class. We never put the package folder itself on the classpath.
- A JAR entry is searched like a folder, from the root of the archive.
- A wildcard entry such as lib/* expands to every .jar and .JAR file in that folder, in an unspecified order. It does not include class files or subfolders.

The -cp option replaces the CLASSPATH variable, and the variable replaces the default, so only one of the three is ever used. The java command uses the current directory (.) only when neither is set. As soon as we pass -cp, the current directory is no longer searched unless we add . to the list.
The order matters when two entries contain the same class. For example, an app that has gson-2.10.1.jar and gson-2.13.2.jar on the classpath gets the class from whichever JAR comes first, which can cause a NoSuchMethodError at runtime when the other version was used at compile time.
2. Setting the Classpath With -cp
The -cp option sets the classpath for one command only, which keeps each app independent of the others. It works the same way for javac and for java, and the long form –class-path has the same meaning.
:: Windows: one JAR, several JARs, and every JAR in a folder
java -cp "classes;lib\units.jar" com.howtodoinjava.recipes.RecipeApp
java -cp "classes;lib\units.jar;lib\gson-2.13.2.jar" com.howtodoinjava.recipes.RecipeApp
java -cp "classes;lib\*" com.howtodoinjava.recipes.RecipeApp
# Linux and macOS: the same with a colon
java -cp "classes:lib/*" com.howtodoinjava.recipes.RecipeApp
We put the classpath in double quotes when it contains a wildcard, because on Linux and macOS the shell would otherwise expand lib/* itself and pass the JAR names as separate arguments. The quotes also protect folder names with spaces on Windows.
The wildcard follows strict rules that cause many failed starts.
| Entry | What the JVM searches |
|---|---|
| lib/* | Every .jar file in lib |
| lib/*.jar | Nothing, because only a bare * is expanded, so the app fails with NoClassDefFoundError |
| lib | Class files below lib, but no JAR files inside it |
| lib/* with JARs in lib/db | Only the JARs at the top level of lib, never those in subfolders |
| * | Every JAR file in the current directory |
Since Java 11, the java launcher also runs a single source file, and since Java 22 a program spread over several source files. The classpath option works there too, so java -cp lib\units.jar src\com\howtodoinjava\recipes\RecipeApp.java compiles the file in memory against units.jar and runs it.
Long classpaths can exceed the Command Prompt limit of 8,191 characters per command line. An argument file solves it, because the launcher reads options from a file whose name starts with @.
:: app.args contains one line: -cp classes;lib\units.jar
java @app.args com.howtodoinjava.recipes.RecipeApp
3. Setting the CLASSPATH Environment Variable
The CLASSPATH environment variable applies to every java and javac command that has no -cp option. A set or export command changes it for the current terminal window only, whereas the Windows settings dialog or a shell profile changes it permanently.
:: Windows Command Prompt, current window only
set CLASSPATH=.;C:\recipes\classes;C:\recipes\lib\*
echo %CLASSPATH%
set CLASSPATH=
# Linux and macOS, current shell only (add the export line to ~/.bashrc or ~/.zshrc to keep it)
export CLASSPATH=".:/opt/recipes/classes:/opt/recipes/lib/*"
echo "$CLASSPATH"
unset CLASSPATH
The empty set CLASSPATH= removes the variable from the window, and unset does the same in a Linux shell. When the variable is not set, echo %CLASSPATH% in the Command Prompt prints the text %CLASSPATH% unchanged, and echo “$CLASSPATH” prints an empty line.
To set the variable permanently on Windows 10 or 11, we follow a few steps.
- Open the Start menu, search for environment variables and select the result Edit environment variables for your account.
- Under User variables, click New, or select an existing CLASSPATH and click Edit.
- Enter CLASSPATH as the name and the entries separated by semicolons as the value, starting with . to keep the current directory.
- Click OK and open a new Command Prompt, because open windows keep the old value.
A global CLASSPATH is rarely a good idea on a developer machine or a server. For example, a reporting tool sets CLASSPATH system-wide to its own old JDBC driver, and a script that starts our import job with plain java picks up that driver too. The -cp option in the script, or an executable JAR, keeps each app on its own classpath, and the guide to setting the classpath from the command line has more command variants.
4. Classpath in Executable JAR Files
With java -jar, the JAR file is the only source of user classes, and the JVM ignores both -cp and CLASSPATH. A JAR that needs other JARs lists them in the Class-Path attribute of its manifest, with paths relative to the location of the JAR file.
# META-INF/MANIFEST.MF of recipe.jar
Main-Class: com.howtodoinjava.recipes.RecipeApp
Class-Path: lib/units.jar
We run the same JAR in both ways. Without the manifest entry, the -cp option has no effect and the app fails, and with the entry, it finds units.jar next to the JAR.
java -cp lib/units.jar -jar recipe.jar # without Class-Path in the manifest
java -jar recipe.jar # with Class-Path: lib/units.jar
Exception in thread "main" java.lang.NoClassDefFoundError: com/howtodoinjava/units/Units
at com.howtodoinjava.recipes.RecipeApp.main(RecipeApp.java:5)
Flour: 300 g
Maven writes the Class-Path entry for us with the JAR plugin, and a fat JAR avoids it by packing all dependencies into one file. The guide to executable JAR files with dependencies shows both setups.
5. Common Classpath Errors
Most classpath problems show up as one of four messages, and each message points to a different mistake. The messages in the table come from JDK 25.
| Message | Cause | Fix |
|---|---|---|
| Error: Could not find or load main class com.howtodoinjava.recipes.RecipeApp | The folder with the compiled classes is not on the classpath, or -cp points to the package folder instead of its root | Pass the root folder, such as -cp classes, and the fully qualified class name |
| Could not find or load main class classes.com.howtodoinjava.recipes.RecipeApp | A file path was passed instead of a class name | Use dots and no folder prefix, and set the folder with -cp |
| NoClassDefFoundError: com/howtodoinjava/units/Units, caused by ClassNotFoundException | The main class was found, but a library it uses is missing at runtime | Add the JAR to -cp, or to Class-Path for java -jar |
| error: package com.howtodoinjava.units does not exist | javac did not get the library on its classpath | Pass the same JAR to javac -cp |
The guide to Could not find or load main class covers more causes of the first error, such as a wrong package declaration. A classpath file is also how apps load configuration files, which the article on reading a file from the classpath explains.
6. Sourcepath vs Classpath vs Module Path vs Build Path
Four similar terms describe where Java tools look for code. The sourcepath and the classpath are options of the JDK tools, the module path is the Java 9 alternative to the classpath for modular JARs, and the build path is an IDE setting that produces the other three.
| Term | Holds | Used by | Option or setting |
|---|---|---|---|
| Sourcepath | .java source files | javac only | –source-path, -sourcepath |
| Classpath | .class files and JAR files | javac and java | -cp, –class-path, CLASSPATH |
| Module path | Modular JARs with a module-info.class | javac and java | -p, –module-path |
| Build path | Source folders, libraries, the JDK and other projects | Eclipse (IntelliJ IDEA calls it module dependencies) | Project properties, or pom.xml and build.gradle |
6.1. The Sourcepath
The sourcepath tells javac where to find source files of classes that our code uses but that we did not list on the command line. The compiler compiles these files too, so in the following example on Linux (on Windows, the list is src;units), javac finds Units.java in the units source folder and writes both class files.
javac -sourcepath src:units -d out src/com/howtodoinjava/recipes/RecipeApp.java
out/com/howtodoinjava/recipes/RecipeApp.class
out/com/howtodoinjava/units/Units.class
When we omit -sourcepath, javac searches the classpath for source files as well, and compiles a source file when it is newer than the matching class file. When we set -sourcepath, source files on the classpath are ignored. The option -implicit:none stops javac from writing class files for the sources it found this way.
6.2. The Module Path
Since Java 9, a JAR with a module-info.class file is a module, and the module path is where the JVM finds modules. Unlike on the classpath, the JVM checks at startup that every required module is present and that no package exists in two modules, so a missing library fails at launch instead of at the first call.
java --module-path mods --module com.howtodoinjava.recipes/com.howtodoinjava.recipes.RecipeApp
Both paths can be used in one command, and most apps, including most Spring Boot apps, still run from the classpath. The Java 9 modules tutorial explains module-info.java in detail.
6.3. The IDE Build Path
In Eclipse, the Java Build Path page of the project properties lists the source folders, the output folder, the libraries and the JDK. Eclipse turns this list into a sourcepath and a classpath when it compiles, and into a classpath when it runs the app. In a Maven or Gradle project, the IDE builds this list from pom.xml or build.gradle, so we change dependencies there, not in the dialog.
7. Java Classpath FAQs
Questions about the classpath mostly come from confusion with other path settings and from commands that work in the IDE but not in the terminal.
7.1. What is the difference between PATH and CLASSPATH?
The operating system uses PATH to find programs such as java.exe and javac.exe. The JVM uses CLASSPATH to find classes. We add the JDK bin folder to PATH, and our classes and JAR files to the classpath.
7.2. Is the current directory on the classpath by default?
Yes, but only when neither -cp nor CLASSPATH is set. Once we set either one, the current directory is searched only if the list contains ..
7.3. Are -cp, -classpath and –class-path the same?
Yes. All three set the same value for java and javac. The –class-path form was added in Java 9 to match the style of the other long options.
7.4. How do we print the classpath of a running app?
We read System.getProperty(“java.class.path”) in the code, as in the intro example. For a running JVM, jcmd <pid> VM.system_properties prints the same property, and in a Maven project mvn dependency:build-classpath prints the classpath of the dependencies.
7.5. Does the classpath search subfolders for JAR files?
No. A folder entry finds class files in its package subfolders, and a lib/* entry finds the JAR files at the top level of lib, but no entry looks for JAR files in subfolders. Each folder with JAR files needs its own wildcard entry.
8. Conclusion
The classpath is the ordered list of folders and JAR files in which the JVM and javac look for classes. The -cp option beats the CLASSPATH variable, which beats the default current directory, and java -jar ignores both and reads the manifest Class-Path instead.
Folder entries are package roots, the wildcard only works as dir/*, and the separator is a semicolon on Windows and a colon elsewhere. The sourcepath, the module path and the IDE build path cover source files, modules and project setup, and the Java tutorial links the other basics.
9. References
- The java Command (Java 25)
- The javac Command (Java 25)
- Setting the Class Path (Oracle)
- JEP 261, Module System
- Eclipse Java Build Path
Happy Learning !!
There is a subtle but serious bug in the code outlined in section 3 that can be instructive to understanding that classpath is where JVM looks for all classes and not just for dependant classes.
The first statement “$ javac –classpath C:\dependency\framework.jar MyApp.Java” compiles fine and places the MyApp.class file in the current directory. However, the second statement “$ java –classpath C:\dependency\framework.jar MyApp” fails with error unable to find MyApp class and requires updating the classpath including the location of MyApp.class which is the current directory in this case.
Thanks for the feedback. Updated the article. It requires to run the
javacandjavacommand from the same directory where the java file is placed.How to set the classpath through our java program dynamically?
should be
Setting Classpath on linux/unix is not working
javac –classpath C:\dependency\framework.jar:C:\location\otherFramework.jar
This costed me a lot of time, because its wrong. On windows, the classpath separator is “;”.
this is really very nice and beautiful article.
thanks for share this.