Java Glossary : classpath

CMP home Java glossary home Menu no menu Last updated 2004-06-28 by Roedy Green ©1996-2004 Canadian Mind Products

Java definitions: 0-9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

You are here : home : Java Glossary : C words : classpath.

classpath
The CLASSPATH is an environment variable that tells the Java compiler javac.exe where to look for class files to import or java.exe where to find class files to interpret.

In contrast, the PATH is an environment variable that tells the command processor the where to look for executable files, e.g. *.exe, *.com and .bat files. The Classpath is one of the most confusing things in Java. Unfortunately, you must master it to even compile HelloWorld.

CLASSPATH And File Naming Recipes

Here are my simplified rules for using CLASSPATH and naming the files on the javac.exe and java.exe command line:
  1. Put every class in a package. Don't use the default package.
  2. Use the latest JDK. It will be the one everyone you ask help from is familiar with. Two dangling prepositions in one sentence. Churchill would be proud.
  3. Configure your SET CLASSPATH= in the environment to clear it out. Avoid JDK 1.0 if you can because its CLASSPATH is more complicated since it has to help javac.exe or java.exe find the standard classes.
  4. You don't need to explicitly include J:\j2sdk1.4.2_04\jre\lib\rt.jar unless you are using Jikes, where you need to add it to the JIKESPATH, but not the CLASSPATH.
  5. In all that follows, everything is strictly case sensitive.
  6. To compile a HelloWorld.java app in the default package in C:\MyDir, use

    CD \MyDir
    javac.exe -classpath . HelloWorld.java
    

  7. To run a HelloWorld.class app, in the default package in C:\MyDir, use

    CD \MyDir
    java.exe -classpath . HelloWorld
    

  8. To compile a HelloWorld.java app in C:\com\mindprod\mypackage, in package com.mindprod.mypackage, use

    CD \
    javac.exe -classpath . com\mindprod\mypackage\HelloWorld.java
    

  9. To run a HelloWorld.class app in C:\com\mindprod\mypackage, in package com.mindprod.mypackage, use

    CD \
    rem not you do not do cd \com\mindprod\mypackage
    java.exe -classpath . com.mindprod.mypackage.HelloWorld
    

  10. To compile a HelloWorld.class app in C:\com\mindprod\mypackage, in into a jar called helloworld.jar in package com.mindprod.mypackage, use


    view

  11. To run a HelloWorld.class app in C:\com\mindprod\mypackage, in a jar called helloworld.jar in package com.mindprod.mypackage, use

    CD \AnyDir
    java.exe -classpath helloworld.jar com.mindprod.mypackage.HelloWorld
    
    rem or if your Main-Class manifest points to HelloWorld.class.
    java.exe -jar helloworld.jar
    
    rem or if your *.jar extension is set to invoke java.exe
    helloworld.jar
    

  12. If for any reason the examples shown do not work with your version of java.exe, try replacing the \ in com\mindprod\mypackage\HelloWorld with / mypackage/HelloWorld.
If you stare long enough at those examples, you may understand the logic behind them, and then you can create variants. If you can't, just slavishly copy the closest matching example.

Rules About Classpaths

  1. The elements of the classpath are platform specific OS directory names or jar file names; the package/classnames on the command line are not. Don't try to concoct a class name such as C:/com.mindprod.mypackage.MyClass
  2. If you want a jar on the classpath, you must put the jar file name on the classpath, not just the name of the directory where the jar lives. This means you need whacking long classpaths, with every jar in a common directory each added to the classpath individually. Perhaps one day Sun will implement a JARPATH. In would not be hard to build a wrapper around Javac.exe and Java.exe that faked in a JARPATH. Hint, hint.
  3. Simply copying or moving your jar files to the ext directory pointed to by the system property java.ext.dirs = C:\Program Files\Java\j2re1.4.2_04\lib\ext automatically puts them on the classpath without having to mention the explicitly. This is a great way to prune back an overblown classpath. It is safest to put your jars in all the ext directories:
    where to look for ext directories :
    You never know for sure where your Javac.exe or java.exe is going to look. Grrr. You can change the location of the ext directory on the command line.

    java.exe -Djava.ext.dirs=c:\mylibs mypackage.MyClass
    

  4. Class names are always fully qualified with the complete package name. There is no way to ever abbreviate the higher levels.
  5. Each element of the CLASSPATH provides a starting point to look for a fully qualified package and class name, identical to the way it appeared in the package or import statement.
  6. If the element of the CLASSPATH is the name of a directory, Java will look in that tree for directory names matching the package name structure. It looks at one place only. It does not search. The class file sought must be filed under the one and only precise fully qualified pathname, or it won't be found. It wants to find a *.class file (or *.java file), at the precisely correct spot in the directory tree. You must get an exact match on the fully qualified name. The name of the directory specified in the CLASSPATH itself is totally immaterial in determining the package name.
  7. If the element of the CLASSPATH is a jar, Java will look in the internal directory structure of the jar for an exact match on the fully qualified name. It looks; it does not search. The class file sought must be filed under the one and only precise fully qualified pathname, or it won't be found. The location of the jar is totally immaterial in determining the name of the package. If you peek inside the jar with WinZip you should see pathnames on each class file matching the package structure. Download and examine any of my jars and the corresponding source to see how it works.
  8. An alternative, ultimately more confusing way of looking at it, is that you specify part of the operating system's name for a class file in the CLASSPATH and part in the package name. Java source imports and package statements, javac.exe and java.exe command lines specify only the fully qualified package name, not the higher order part handled by the CLASSPATH. The higher levels that are handled by the CLASSPATH (which could appear on the command line via -classpath option), are effectively invisible to your Java programs. However, you are not at liberty to shuffle levels of qualification between your import and classpath unless you adjust all your package statements and recompile as well.

Spaces and Quotes in Classpaths

Spaces in filenames are a royal PITA, however, Microsoft forces them down your throat because most packages install in C:\Program Files. There are several plausible ways you might deal with spaces in classpaths: javac.exe and java.exe are fairly forgiving. Here is what works and what does not: rem no quotes on the command line.
javac -classpath .;C:\;C:\Program Files\Java Web Start\javaws.jar;E:\jaf-1.0.1\activation.jar *.java

rem quotes around whole classpath on the command line.
javac -classpath ".;C:\;C:\Program Files\Java Web Start\javaws.jar;E:\jaf-1.0.1\activation.jar" *.java

rem quotes around each element of the classpath on the command line.
javac -classpath ".;C:\;C:\Program Files\Java Web Start\javaws.jar;E:\jaf-1.0.1\activation.jar" *.java

rem no quotes on the classpath environment variable.
set classpath=.;C:\;C:\Program Files\Java Web Start\javaws.jar;E:\jaf-1.0.1\activation.jara
javac *.java

rem quotes around whole classpath environment variable.
set classpath=".;C:\;C:\Program Files\Java Web Start\javaws.jar;E:\jaf-1.0.1\activation.jar"
javac *.java

rem quotes around each element of the classpath environment variable.
set classpath=".;C:\;"C:\Program Files\Java Web Start\javaws.jar";"E:\jaf-1.0.1\activation.jar"
javac *.java
There is some logic to it. The command line needs quotes around the entire classpath to tell it apart from any other command line options. SET CLASSPATH= needs no quotes because the end of line terminates the classpath. The simplest rule is always put to always put quotes around the entire classpath, even though they are not necessary for SET CLASSPATH=.

CLASSPATH Tips

CLASSPATH Complexities

I lied to you. Life is actually a little more complicated. If you feel ready for the whole truth, and want to understand the logic behind those examples, here is how CLASSPATH really works. Suddenly all of classpath's craziness made sense once I figured out how it worked inside. You may be similarly lucky.

The Key To Understanding

This all sounds hideously complicated. My explanations sound like drooling nonsense. It did not come clear to me until I began to think about how java.exe and javac.exe make use of the classpath. Then it all made sense.
  1. When java.exe (or <APPLET CODE) wants to find a class, it has the fully qualified classname composed of package.classname e.g. com.mindprod.business.HelloWorld.
  2. It then looks at each element (a chunk between semicolons) of the CLASSPATH, working left to right seeking a match.
  3. If that CLASSPATH element is a jar, it looks for an entry inside the jar for a folder called precisely com/mindprod/business and a member called precisely HelloWorld.class. It is irrelevant to the naming scheme where in the directory structure the jar file itself is. All that matters is perfect-fully-qualified-pathnames-to-package mapping inside the jar.
  4. If the CLASSPATH element is a directory, it expects to find in that directory a directory subtree called precisely com\mindprod\business and in the business directory it expects to find a file called precisely HelloWorld.class. It does not matter where the CLASSPATH element itself is in the directory tree. That has no effect on the package name.
  5. The lookup is quite quick for each element of the classpath. It involves no scanning, just a lookup, does this class file exist by precisely this name in precisely this place? It does though have to repeat this for each element of the classpath before it gives up.
  6. When javac.exe wants to find a class, it may want either the *.java source or the compiled *.class or both. It uses the same mechanism to find them.

The Hashtable Explanation

If you understand Hashtables, this explanation may let you suddenly grok the classpath.

A ClassLoader with plenty of RAM could work this way. It creates a giant Hashtable of all possible classes out there on disk in all the directories and jars on the classpath and all the ext directory jars, using fully qualified package and class names as the keys. It would include classes it might never even possibly load. A real implementation would use some tricks to conserve RAM such as making a Hashtable of Hashtables, one for each layer of the package name, or keys broken into interned segments, or might only build a Hashtable for jarred classes, but for the purpose of understanding, imagine just a simple single Hashtable with the keys to all the fully qualified package and classnames on the classpath.

How does the ClassLoader build this Hashtable? It looks at the first segment of the classpath and starts adding classnames using the fully qualified class name as the key and where the class files are on disk as the value. Then it moves onto the next segment of the classpath. It adds all those classnames. If it discovers a duplicate, it ignores the new key, and keeps the key it already has. This ensures the first occurrence of a class on the classpath will be the one used.

Now when you first use a class, the ClassLoader looks up the name in the Hashtable, and it if it is present, it knows where on disk and in what jar to find it. There is no scanning required, just a straight forward keyed Hashtable lookup. If the class is not present in the Hashtable, the ClassLoader knows the class is nowhere to be found and it raises the dreaded NoClassDefFoundError exception.

Classpath Example

If, for example, you had a class called com.mindprod.bulk.Resend e.g. class Resend in package com.mindprod.bulk,

If you did cd \ and had classpath . then java would expect to find the class file in: C:\com\mindprod\bulk\Resend.class.

If you did cd \com\mindprod\bulk and had classpath . then java would expect to find the class file in: C:\com\mindprod\bulk\com\mindprod\bulk\Resend.class.

If you did cd \ and had classpath C:\ then it would expect to find the class file in: C:\com\mindprod\bulk\Resend.class.

If you did cd \com\mindprod\bulk and had classpath C:\ then it would expect to find the class file in: C:\com\mindprod\bulk\Resend.class.

To get the hang of this, experiment with simple classpaths with only one element to them, then gradually build up more complex classpaths that search in many places.

java.ext.dirs

Sometimes you will have so many jar files, you can't fit them all on the classpath. What you can do then is look at the system property,

System.getProperty( "java.ext.dirs" );

which you can view by running wassup as an application or Applet. Then put the jar in the corresponding directory. e.g.

java.ext.dirs = D:\program files\JavaSoft\JRE\1.3\lib\ext

The jars will automatically be found without putting them on the classpath.

There are at least two ext directories:

where additional jars on the path are kept :
java.exe seems to use the JRE version and where javac.exe seems to use the JDK version.

Sooner or later some you will have to reinstall and you will lose your ext directories. You can quickly rebuild them if you maintain a bat file like this. Adjust the file to account for where your ext dirs are and where the jars are you need.

REM fixExt -- copy jars to ext for auto classpath

Rem why are there two EXT dirs?? lord knows.
rem classpath should be simply C:\;E:\;.
C:
CD "J:\j2sdk1.4.2_04\jre\lib\ext"

copy "c:\jaf-1.0.1\activation.jar"
copy "c:\javamail-1.2\mail.jar"
copy "c:\Program Files\JMF2.1.1\lib\jmf.jar"
copy "c:\Program Files\JMF2.1.1\lib\sound.jar"

CD "C:\Program Files\Java\j2re1.4.2_04\lib\ext"

copy "c:\jaf-1.0.1\activation.jar"
copy "c:\javamail-1.2\mail.jar"
copy "c:\Program Files\JMF2.1.1\lib\jmf.jar"
copy "c:\Program Files\JMF2.1.1\lib\sound.jar"
rem -30-

Command Line Too long?

In Windows in particular, you will often find all the junk you need to put on a command line is too long. Here are a few tricks to shorten it.

Global Classpath Is An Anachronism

The global classpath is an anachronism. It is impossible to have one classpath that satisfies all possible compilations and all possible applications. Installers will meddle with it. Programs will work, then mysteriously stop working when you make some innocent change the classpath.

Instead, put it in your IDE projects, on your javac.exe -classpath and java.exe -classpath commands and in your jar manifests where the rest of the world cannot meddle with it.

Avoid using version numbers in your classpaths. They tend to go stale.

If you leave out your SET classpath, it defaults to simply . the current directory.

Servlets

When you write servlets, JSP, Struts and the like, the classpath is extended with the WEB-APP\classes directory for additional class files for a particular application, and WEB-APP\lib for jars for a particular application. Instead of adding jars and directories to the general classpath, you make multiple copies off the classes and jars and put them in the various WEB-APPs as needed. This helps minimize unexpected interactions between applications, e.g. one app needs version 1.1 of a jar and another version 2.0.

Learning More


CMP logo
CMP_home
home
Canadian Mind Products CSS
HTML Checked!
ICRA ratings logo
mindprod.com IP:[24.87.56.253]
Your IP:[80.134.30.163]
You are visitor number 38265.
Please send errors, omissions and suggestions
to improve this page to Roedy Green.
You can get a fresh copy of this page from: or possibly from your local J: drive mirror:
http://mindprod.com/jgloss/classpath.html J:\mindprod\jgloss\classpath.html