Including all the jars in a directory within the Java classpath
Using Java 6 or later, the classpath option supports wildcards. Note the following:
- Use straight quotes (
"
) - Use
*
, not*.jar
Windows
java -cp "Test.jar;lib/*" my.package.MainClass
Unix
java -cp "Test.jar:lib/*" my.package.MainClass
This is similar to Windows, but uses :
instead of ;
. If you cannot use wildcards, bash
allows the following syntax (where lib
is the directory containing all the Java archive files):
java -cp "$(printf %s: lib/*.jar)"
(Note that using a classpath is incompatible with the -jar
option. See also: Execute jar file with multiple classpath libraries from command prompt)
Understanding Wildcards
From the Classpath document:
Class path entries can contain the basename wildcard character
*
, which is considered equivalent to specifying a list of all the filesin the directory with the extension.jar
or.JAR
. For example, theclass path entryfoo/*
specifies all JAR files in the directory namedfoo. A classpath entry consisting simply of*
expands to a list of allthe jar files in the current directory.A class path entry that contains
*
will not match class files. Tomatch both classes and JAR files in a single directory foo, use eitherfoo;foo/*
orfoo/*;foo
. The order chosen determines whether theclasses and resources infoo
are loaded before JAR files infoo
, orvice versa.Subdirectories are not searched recursively. For example,
foo/*
looksfor JAR files only infoo
, not infoo/bar
,foo/baz
, etc.The order in which the JAR files in a directory are enumerated in theexpanded class path is not specified and may vary from platform toplatform and even from moment to moment on the same machine. Awell-constructed application should not depend upon any particularorder. If a specific order is required then the JAR files can beenumerated explicitly in the class path.
Expansion of wildcards is done early, prior to the invocation of aprogram's main method, rather than late, during the class-loadingprocess itself. Each element of the input class path containing awildcard is replaced by the (possibly empty) sequence of elementsgenerated by enumerating the JAR files in the named directory. Forexample, if the directory
foo
containsa.jar
,b.jar
, andc.jar
, thenthe class pathfoo/*
is expanded intofoo/a.jar;foo/b.jar;foo/c.jar
,and that string would be the value of the system propertyjava.class.path
.The
CLASSPATH
environment variable is not treated any differently fromthe-classpath
(or-cp
) command-line option. That is, wildcards arehonored in all these cases. However, class path wildcards are nothonored in theClass-Path jar-manifest
header.
Note: due to a known bug in java 8, the windows examples must use a backslash preceding entries with a trailing asterisk: https://bugs.openjdk.java.net/browse/JDK-8131329
Under Windows this works:
java -cp "Test.jar;lib/*" my.package.MainClass
and this does not work:
java -cp "Test.jar;lib/*.jar" my.package.MainClass
Notice the *.jar
, so the * wildcard should be used alone.
On Linux, the following works:
java -cp "Test.jar:lib/*" my.package.MainClass
The separators are colons instead of semicolons.
We get around this problem by deploying a main jar file myapp.jar
which contains a manifest (Manifest.mf
) file specifying a classpath with the other required jars, which are then deployed alongside it. In this case, you only need to declare java -jar myapp.jar
when running the code.
So if you deploy the main jar
into some directory, and then put the dependent jars into a lib
folder beneath that, the manifest looks like:
Manifest-Version: 1.0Implementation-Title: myappImplementation-Version: 1.0.1Class-Path: lib/dep1.jar lib/dep2.jar
NB: this is platform-independent - we can use the same jars to launch on a UNIX server or on a Windows PC.