The Classpath

The concept of a path should be familiar to anyone who has worked on a DOS or Unix platform. It’s an environment variable that provides an application with a list of places to look for some resource. The most common example is a path for executable programs. In a Unix shell, the PATH environment variable is a colon-separated list of directories that are searched, in order, when the user types the name of a command. The Java CLASSPATH environment variable, similarly, is a list of locations that are searched for Java class files. Both the Java interpreter and the Java compiler use the CLASSPATH when searching for packages and Java classes.

An element of the classpath can be a directory or a JAR file. Java also supports archives in the conventional ZIP format, but JAR and ZIP are really the same format. JARs are simple archives that include extra files (metadata) that describe each archive’s contents. JAR files are created with the JDK’s jar utility; many tools for creating ZIP archives are publicly available and can be used to inspect or create JAR files as well. The archive format enables large groups of classes and their resources to be distributed in a single file; the Java runtime automatically extracts individual class files from the archive as needed.

The precise means and format for setting the classpath vary from system to system. On a Unix system (including Mac OS X), you set the CLASSPATH environment variable with a colon-separated list of directories and class archive files:

    %export CLASSPATH=/home/vicky/Java/classes:/home/josh/lib/foo.jar:.

This example specifies a classpath with three locations: a directory in the user’s home, a JAR file in another user’s directory, and the current directory, which is always specified with a dot (.). The last component of the classpath, the current directory, is useful when you are tinkering with classes.

On a Windows system, the CLASSPATH environment variable is set with a semicolon-separated list of directories and class archive files:

    C:\> set CLASSPATH=C:\home\vicky\Java\classes;C:\home\josh\lib\foo.jar;.

The Java launcher and the other command-line tools know how to find the core classes, which are the classes included in every Java installation. The classes in the java.lang, java.io, java.net, and javax.swing packages, for example, are all core classes so you do not need to include these classes in your classpath.

The classpath may also include “*” wildcards that match all JAR files within a directory. For example:

export CLASSPATH=/home/pat/libs/*

To find other classes, the Java interpreter searches the elements of the classpath in order. The search combines the path location and the components of the fully qualified class name. For example, consider a search for the class animals.birds.BigBird. Searching the classpath directory /usr/lib/java means the interpreter looks for an individual class file at /usr/lib/java/animals/birds/BigBird.class. Searching a ZIP or JAR archive on the classpath, say /home/vicky/myutils.jar, means that the interpreter looks for component file animals/birds/BigBird.class within that archive.

For the Java runtime, java, and the Java compiler, javac, the classpath can also be specified with the -classpath option:

    % javac -classpath /home/pat/classes:/utils/utils.jar:. Foo.java

If you don’t specify the CLASSPATH environment variable or command-line option, the classpath defaults to the current directory (.); this means that the files in your current directory are normally available. If you change the classpath and don’t include the current directory, these files will no longer be accessible.

We suspect that about 80 percent of the problems that newcomers have when first learning Java are classpath-related. You may wish to pay particular attention to setting and checking the classpath when getting started. If you’re working inside an IDE, it may remove some or all of the burden of managing the classpath. Ultimately, however, understanding the classpath and knowing exactly what is in it when your application runs is very important to your long-term sanity. The javap command, discussed next, can be useful in debugging classpath issues.

javap

A useful tool to know about is the javap command. With javap, you can print a description of a compiled class. You don’t need the source code, and you don’t even need to know exactly where it is, only that it is in your classpath. For example:

    % javap java.util.Stack

prints the information about the java.util.Stack class:

Compiled from "Stack.java"
public class java.util.Stack<E> extends java.util.Vector<E> {
  public java.util.Stack();
  public E push(E);
  public synchronized E pop();
  public synchronized E peek();
  public boolean empty();
  public synchronized int search(java.lang.Object);
}

This is very useful if you don’t have other documentation handy and can also be helpful in debugging classpath problems. Using javap, you can determine whether a class is in the classpath and possibly even which version you are looking at (many classpath issues involve duplicate classes in the classpath). If you are really curious, you can try javap with the -c option, which causes it to also print the JVM instructions for each method in the class!

Get Learning Java, 4th Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.