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 app 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 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. 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 an 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:

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


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 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=D:\users\vicky\Java\classes;


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. You don't need to include these classes in your classpath; the Java interpreter and the other tools include them automatically. To find other classes, the Java interpreter searches the elements of the classpath in order. The search combines the path location and 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/Java/utils/classutils.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/myutils.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 app 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 have to have the source code, and you don't even have 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 extends java.util.Vector {
 public java.util.Stack( );
 public java.lang.Object push(java.lang.Object);
 public synchronized java.lang.Object pop( );
 public synchronized java.lang.Object 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 feeling really adventurous, you can try javap with the -c option, which causes it to also print the JVM instructions for each method in the class!

Comments