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 Recipes
Here are my simplified rules for using CLASSPATH and
naming the files on the javac.exe and java.exe command line:
- Put every class in a package.
Don’t use the default package.
- 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.
- Configure your SET CLASSPATH= in the environment to
clear it out.
- You don’t need to explicitly include rt.jar:
rt.jar system class files :
unless you are using Jikes, where you
need to add it to the JIKESPATH, but not the CLASSPATH.
- In all that follows, everything is strictly case-sensitive.
- To
cd \MyDir
javac.exe -classpath . HelloWorld.java
- To
cd \MyDir
java.exe -classpath . HelloWorld
- To compile a HelloWorld.java app in J:\com\mindprod\mypackage\, in package com.mindprod.mypackage, use
c:
cd \
javac.exe -classpath . com\mindprod\mypackage\HelloWorld.java
e:
cd E:\com\mindprod\mypackage
javac.exe -classpath .;C:\ HelloWorld.java
- To run a HelloWorld.class app in J:\com\mindprod\mypackage\, in package com.mindprod.mypackage, use
c:
cd \
java.exe -classpath . com.mindprod.mypackage.HelloWorld
- To compile a HelloWorld.class app in J:\com\mindprod\mypackage\, in into a jar called helloworld.jar in package com.mindprod.mypackage, use
- To run a HelloWorld.class app in J:\com\mindprod\mypackage\, in a jar called helloworld.jar in package
CD \dirwherejaris
java.exe -classpath helloworld.jar com.mindprod.mypackage.HelloWorld
java.exe -jar helloworld.jar
helloworld.jar
- 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.
- Note the : or ; is a
separator, not a terminator. You do not put one on the end of the classpath.
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.
Adding Jars to the Classpath
There are 5 ways to put jars on the
classpath:
- Include the individual jar names the set
classpath.
- Include the individual jar names in the -classpath
command line option.
- Include the individual jar names in the Class-Path
option in the manifest.
- In Java version 1.6 or later, use a
wildcard to include all jars in a directory into the
set classpath or the command line -classpath.
java.exe -classpath C:\jardir\*;E:\morejars\*
- Put the jars in the ext directory.
Classpath Gotchas
Classpath Raspberries
- One would think a platform-independent language would have a
platform-independent way of controlling the CLASSPATH, but it doesn’t.
Webgain’s SC.INI is closest, but they are no more.
Sooner or later you will install ANT or
Maven and use it to build your projects in
a platform-independent way. Do it sooner rather than later. It will save you many
headaches even though getting started with ANT (A Neat Tool)
is daunting. The problem is, as a newbie, ant is just too over whelming. You must
use the clutzy classpath only to discard it once you have mastered it.
- In Linux and (and NT, W2K, XP, W2003, Vista, W2008, W7-32, W7-64, W8-32, W8-64, W2012, W10-32 and W10-64
under bash, the elements of the CLASSPATH are separated
by colons. In W95, W98, Me, NT, W2K, XP, W2003, Vista, W2008, W7-32, W7-64, W8-32, W8-64, W2012, W10-32 and W10-64, they are separated by semicolons. The separator
character is variable with different platforms, but determinable from File. pathSeparatorChar. Sun deserves a
major raspberry. A pure Java-feature deserves universal consistency.
Where the Classpath Hides
Stalking your classpath, you must
look in different places depending on the platform:
- For NT, W2K, XP, W2003, Vista, W2008, W7-32, W7-64, W8-32, W8-64, W2012, W10-32 and W10-64, since there is no autoexec.bat, you have to preload the environment strings into the
environment with Settings ⇒ Control Panel ⇒ system
⇒ environment. You can use traditional BAT (Batch)
files to create them, then echo, copy and paste them into the permanent
environment. Remember to click set before you click
OK or your new settings will be discarded. Also see
the rules above for dealing with
directory of jar filenames containing blanks Alternatively always install your
apps in directories without embedded spaces. Make sure you have no lead or trail
spaces on the classpath as a whole. The Control Panel uses a microscopic
unreadable font. To proofread, copy/paste to an editor. Beware of spurious spaces
introduced by copy/pasting.
- Linux controls the environment with export CLASSPATH=
in your .bashrc file.
- Windows 95/98 controls the environment with SET
CLASSPATH= in autoexec.bat.
- Browsers use the CLASSPATH in
the standard SET environment.
- Internet Explorer hides its CLASSPATH in the
registry under HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Java VM.
- For Servlet wombs, each
application gets its own CLASSPATH in a complex way.
You will have to read your womb’s documentation.
- SlickEdit® creates a classpath
composed of the files included in the current project.
Rules About Classpaths
- Simply copying or moving your jar files to the ext
directory pointed to by the system property java.ext.dirs =
C:\Program Files\java\jre1.8.0_131\
\lib\ext\ automatically puts them on the classpath without having to
mention them 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 java.exe -Djava.ext.dirs=C:\mylibs mypackage.MyClass
See the ext dirs entry for details.
- Class names are always fully qualified with the complete
package name. There is no way to ever abbreviate the higher levels.
- 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.
- 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.
- 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.
- 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:
- Avoid spaces altogether. Don’t put packages in
C:\Program Files\
unless you have to.
- do nothing special.
- Put quotes around the entire classpath.
- Put quotes around each element of the classpath.
javac.exe and java.exe
are fairly forgiving. Note that just to keep you on your toes:
- The rules are different for the -classpath on the
command line and the classpath SET environment variable,
usually set in the Control Panel ⇒ System ⇒
Advanced or with SET classpath=.
- If you make a mistake, you don’t get a specific error message. It just
can’t find the classes in the jars on the classpath.
Here is what works and what does not:
javac -classpath .;C:\;J:\Program
Files\javamail1.4\mail.jar;J:\Program Files\jaf1.1\activation.jar
*.java
javac -classpath .;C:\;J:\Program
Files\javamail1.4\mail.jar;J:\Program Files\jaf1.1\activation.jar
*.java
javac -classpath .;C:\;J:\Program
Files\javamail1.4\mail.jar;J:\Program
Files\jaf1.1\activation.jar *.java
set classpath=.;C:\;J:\Program
Files\javamail1.4\mail.jar;J:\Program Files\jaf1.1\activation.jar
javac.exe *.java
set classpath=.;C:\;J:\Program
Files\javamail1.4\mail.jar;J:\Program Files\jaf1.1\activation.jar
javac *.java
set classpath=.;C:\;J:\Program Files\javamail-1.5.4\javax.mail.jar;J:\Program Files\jaf1.1\activation.jar
javac.exe *.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=.
Dots in Path, Classpath and java.library.path
In Windows, a dot in the environment PATH means search the current directory. Normally you leave it out and one is presumed at the head of the PATH.
In all OSes, in the classpath, a dot means search the current directory. If you leave it out, the current directory will not be searched for class files.
Java creates the java.library.path from the environment PATH, adding to it. If it finds no dot in the PATH,
it adds one at the end of the java.library.path.
In the Mac dot is automatically included in the java.library.path.
CLASSPATH Tips
- See below for tip on how to
squeeze long classpath onto the command line.
- Unlike C++, Java compilers use the
CLASSPATH to find and examine compiled code rather than
source header files to learn how about how to invoke the various methods. The
compiler also uses the CLASSPATH to find and compile
the corresponding source if no class file is available. The runtime also uses the
CLASSPATH to find the class files to execute.
- Note that CLASSPATH uses forward (or optionally
backslashes under Windows W95, W98, Me, NT, W2K, XP, W2003, Vista, W2008, W7-32, W7-64, W8-32, W8-64, W2012, W10-32 and W10-64
to separate levels and semicolons to separate directories, (in general
File. pathSeparatorChar
directory separators). In contrast, inside Java programs in import statements, you use dots to separate levels. Inside
<lt;APPLET CODE statements it is best if you use dots
to represents levels inside jar files and slashes to represent files. java.exe uses only dots, no slashes or backslashes allowed.
- Presuming
SET CLASSPATH=.;E:\com\mindprod\project;
You might think that you could have an import like this:
import com.mindprod.project.mybeans.Jumping;
However, you cannot respecify any level already mentioned in the CLASSPATH. You
just give the low levels of qualification
- If you have a jar file in C:\MyStuff\ajar.jar,
on the classpath, then com.mindprod.somepackage is
the internal directory name stored inside the jar file. You might be tempted to
might try to get at the class in the jar with the following import:
import MyStuff.com.mindprod.somepackage.SomeClass;
That will not work. You may only specify the low order qualification that is
actually part of the package name
import com.mindprod.somepackage.SomeClass;
- Basically the rule is, your package name cannot provide redundant information
that the CLASSPATH has already provided. You always
have to specify the fully qualified package name. You can’t abbreviate with a
smart
SET CLASSPATH=.;E:\com\mindprod\mypackage;
Then expect to get away with specifying only MyClass
instead of com.mindprod.mypackage.MyClass. You
always have to use fully qualified class names.
echo %CLASSPATH%
under W95, W98, Me, NT, W2K, XP, W2003, Vista, W2008, W7-32, W7-64, W8-32, W8-64, W2012, W10-32 and W10-64
or echo $CLASSPATH
under Unix/Linux.
If you want to be really sure, use the Wassup utility which will also find and report on
Webgain’s SC.INI CLASSPATH when it applies.
- If you don’t want to be bothered with manually composing a CLASSPATH, try
SmartJ, though it is now badly out of date
in JDK (Java Development Kit)
support.
- For applications, you can also specify the CLASSPATH on the command line with the -classpath or -cp (for short) option
switch, e. g.
java.exe -cp C:\MyStuff;C:\MyStuff\mygoodies.jar HelloWorld
This is the safest place especially when every app needs a slightly different
CLASSPATH and/or a different
JVM (Java Virtual Machine). The catch is the CLASSPATH can be very long which makes the command line hard to
type and read. Infuriatingly, the -cp shortcut does not
work with javac.exe as well.
- Keep in mind that Java is extremely case-sensitive, even if your operating
system is not. Be very careful to get case precisely right any time you specify a
filename, <APPLET CODE, or CLASSPATH. Unfortunately
Windows and Windows NT will often lie to you about the actual case of a name.
Tracking down case mismatches can drive you nuts. JP Soft’s tcc/TakeCommand DIR /F is
useful at getting at the true case of a filename. Packages should contain lower
case only. Classes should start with an upper case letter. Variables should start
with a lower case letter. See coding conventions.
- Just to keep you on your toes, in JDK
1.0 putting the classes.zip
on the CLASSPATH is mandatory. in
Java version 1.1, putting classes.zip on the CLASSPATH is optional.
In 1.2 and 1.3 putting rt.jar on the classpath is an
error. Starting with version 1.2 the class files live
in: and they
automatically go on the classpath.
- See java.exe for a more discussion of
how the java.exe runtime uses package names, class
names and the CLASSPATH to find the classes and
javac.exe for how the javac.exe compiler finds the dependent *.java files that also need compilation.
- You have little control over the CLASSPATH used by
a browser for an Applet. You have to grant it security permission to look at your
classpath. If that does not work, try Wassup.
- I lost pounds of hair fighting with classpath. I have found some magic patterns
that work and now just stomp out boiler plate to create the skeleton java,
HTML (Hypertext Markup Language)
and bat files for new projects. You might study my jar
files and Applet HTML
and emulate my patterns. See the downloads page.
You can use my ANT
scripts as a starting point. I long ago gave up on using
BAT
files.
- To discover what your program is using as the classpath use:
You can view the default value of these properties by running wassup as an application. The CLASSPATH separator character is platform dependent. You can
discover it with the system properties as well. It will usually be ; or :. You must put ., the current directory, explicitly on the CLASSPATH.
- If you use the -jar option, java.exe ignores the classpath. It will only look in that
jar.
- Classpath will make a lot more sense if you start with some jars and bat files
that work and study them, looking inside the zips and jars with WinZip.
- The Webgain (née Symantec) compilers ignored the usual SET CLASSPATH= and take one from the \vcp\bin\sc.ini file instead. Class files may be standalone, combined
in zip files or combined in jar files. Java looks for class files in any
directories mentioned in the CLASSPATH, but only searches jar and zip files if they
are explicitly mentioned. A typical CLASSPATH statement
might
all on one gigantic line without any spaces. Ouch!
- My personal classpath looks like this: SET
CLASSPATH=.;C:\;C:\exper;E:\. This will look for classes in the current
path, or in a directory matching the package on C:\,
C:\exper or E:\. I keep most of
my class files in J:\com\mindprod\xxxx\ where the package
is com.mindprod.xxxx, or in C:\exper when there is no package.
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.
- You must put the fully qualified name of the class on the java.exe command line. If there is no package, the name is
simply HelloWorld. e.g.
CD \MyStuff
java.exe HelloWorld
However, had you used a package com.mindprod.business;
clause, then the full name of HelloWorld is
com.mindprod.business.HelloWorld. It must be spelled
with perfect attention to upper/lower case.
- You may not abbreviate the name in any way. It must be 100% fully qualified, always.
- That settled, where should the com.mindprod.business.HelloWorld.class file live? It could live in a
jar file on the CLASSPATH. Inside the jar it must be stored with its fully
qualified name.
CD \jardir
java.exe -cp mystuff.jar com.mindprod.business.HelloWorld
- The class may also live as a free-standing class file. Let us assume that
. (the current directory) is on the CLASSPATH and that
the fully qualified name of the class is com.mindprod.business.MyClass. You cannot put
HelloWorld.class in the current directory. java.exe won’t find it. It will look for it three levels
deeper in as com\mindprod\business\HelloWorld.class. If
it is not there, it won’t find it. It will ignore copies in the current
directory and in .\com.mindprod. You must coax it into
CD \
set classpath=.
java.exe com.mindprod.business.HelloWorld
or CD \com\mindprod\business
java.exe -cp ..\..\..\ com.mindprod.business.HelloWorld
or like java.exe -cp C:\ com.mindprod.business.HelloWorld
- However, that last solution is dangerous and slow because you are exposing your
entire drive to be searched for classes. It is unwise to hang your class
directories directly off the root. Instead hang your directory tree under
C:\cl\.
Then you could write.
CD \cl
java.exe -cp . com.mindprod.business.HelloWorld
or CD cl\com\mindprod\business
java.exe -cp ..\..\..\ com.mindprod.business.HelloWorld
This time only the cl directory is exposed to being
searched for class files.
- com.mindprod.business.HelloWorld may also live as a
free-standing class file hanging off one of the directories mentioned in the
CLASSPATH. Let us assume that C:\MyStuff\
is on the CLASSPATH. You cannot put HelloWorld.class directly in the C:\MyStuff\
directory. java.exe won’t find it. It will look for it three
levels deeper in as
C:\MyStuff\com\mindprod\business\HelloWorld.class.
If it is not there, it won’t find it.
java.exe -cp C:\MyStuff com.mindprod.business.HelloWorld
- These same rules apply to finding all the classes, not just
the one mentioned on the command line. Your directory structure, names and class
file placement must perfectly reflect your package structure which must also
perfectly reflect your structure for storing the *.java source code files in
directories or inside jar files.
- Inside a jar, class names are fully qualified with package and class name using
dots. To execute class com.mindprod.business.MyClass
inside jar myjar.jar:
java.exe -jar C:\someplace\myjar.jar com.mindprod.business.MyClass
- It is still even more complicated than that. java.exe looks for your classes on each element of the
CLASSPATH. You might put C:\;C:\MyStuff;C:\Mystuff\Project99
all on the CLASSPATH. Then you would have several options to the way you specify
your classes, each one dovetailing with a different piece of the CLASSPATH.
Under the Hood: 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.
- 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.
- It then looks at each element (a chunk between semicolons/pathSeparators) of
the CLASSPATH, working left to right seeking a match.
- 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.
- 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.
- 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.
- 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
Stranger in a Strange Land
the classpath.
A ClassLoader with plenty of RAM (Random Access Memory)
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 Examples
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:
J:\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:
J:\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:
J:\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:
J:\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.
ext Directories
The ext dir is a much easier way to add whole jars
to the class path. See the ext dirs entry for
details. I almost never use the old classpath any more.
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.
- Use the SET CLASSPATH in a kickoff bat file for
each application. That way it does not need to be on the java.exe command line with everything else.
- Build
set classpath = C:\somedir\jar
set classpath = %CLASSPATH%;C:\anotherdir
set classpath = %CLASSPATH%;C:\yetanotherdir
You can still get in trouble if the final result is too long.
- Move jars into the ext directory. Then they
don’t need to be on the classpath.
- Instead of passing all parameter with the -D option, put them in a properties
file.
- Use 4DOS or tcc/TakeCommand for your command processor. They have more
relaxed limits.
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 (Integrated Development Environment)
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.
Servlet Wombs
When you write servlets,
JSP (Java Server Pages), Struts and or code for other application servers, the
womb may simulate a common classpath and possibly a classpath for each application.
You will have to read the womb documentation to find out where you put your class
files and resources.
The womb sometimes extends the set classpath 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.
Where Did that Class Come From?
Sometimes you want to know where a
class or resource came from. Which jar, which directory. This may help track down
Sometimes you can’t even find the jar, much less put it on the classpath. I
have written some .help for that
problem.
You also might like to implement the which and what utilities.
Learning More